mirror of https://github.com/AxioDL/metaforce.git
Some hacks for TEV stage handling
This commit is contained in:
parent
44a4d667b7
commit
14a82a678a
|
@ -311,6 +311,8 @@ u32 CCubeMaterial::HandleColorChannels(u32 chanCount, u32 firstChan) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
|
aurora::gfx::set_chan_mat_src(GX::COLOR0A0, GX::SRC_REG);
|
||||||
|
aurora::gfx::set_chan_mat_src(GX::COLOR1A1, GX::SRC_REG);
|
||||||
return chanCount;
|
return chanCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,12 @@ u32 CTevPass::sNextUniquePass = 0;
|
||||||
|
|
||||||
void CTevPass::Execute(ERglTevStage stage) const {
|
void CTevPass::Execute(ERglTevStage stage) const {
|
||||||
if (*this == skPassThru) {
|
if (*this == skPassThru) {
|
||||||
|
// TODO proper handling of # tev stages
|
||||||
|
if (stage > ERglTevStage::Stage0) {
|
||||||
aurora::gfx::disable_tev_stage(stage);
|
aurora::gfx::disable_tev_stage(stage);
|
||||||
|
} else {
|
||||||
|
aurora::gfx::disable_tev_stage(ERglTevStage::Stage1);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
aurora::gfx::update_tev_stage(stage, x4_colorPass, x14_alphaPass, x24_colorOp, x38_alphaOp);
|
aurora::gfx::update_tev_stage(stage, x4_colorPass, x14_alphaPass, x24_colorOp, x38_alphaOp);
|
||||||
aurora::gfx::set_tev_order(static_cast<GX::TevStageID>(stage), GX::TEXCOORD_NULL, static_cast<GX::TexMapID>(stage),
|
aurora::gfx::set_tev_order(static_cast<GX::TevStageID>(stage), GX::TEXCOORD_NULL, static_cast<GX::TexMapID>(stage),
|
||||||
|
|
|
@ -16,13 +16,8 @@ void CGuiPane::Draw(const CGuiWidgetDrawParms& parms) {
|
||||||
auto col = xa8_color2;
|
auto col = xa8_color2;
|
||||||
col.a() = parms.x0_alphaMod * xa8_color2.a();
|
col.a() = parms.x0_alphaMod * xa8_color2.a();
|
||||||
|
|
||||||
#if 0
|
|
||||||
CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::skPassThru);
|
CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::skPassThru);
|
||||||
CGraphics::DrawPrimitive(GX::Primitive::TRIANGLESTRIP, xc0_verts.data(), skDefaultNormal, col, xc0_verts.size());
|
CGraphics::DrawPrimitive(GX::Primitive::TRIANGLESTRIP, xc0_verts.data(), skDefaultNormal, col, xc0_verts.size());
|
||||||
#else
|
|
||||||
aurora::gfx::queue_colored_quad_verts(aurora::gfx::CameraFilterType::Blend, aurora::gfx::ZComp::Always, false, col,
|
|
||||||
xc0_verts);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
CGuiWidget::Draw(parms);
|
CGuiWidget::Draw(parms);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <compare>
|
#include <compare>
|
||||||
#include <vector>
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "Runtime/RetroTypes.hpp"
|
#include "Runtime/RetroTypes.hpp"
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "movie_player/shader.hpp"
|
#include "movie_player/shader.hpp"
|
||||||
#include "stream/shader.hpp"
|
#include "stream/shader.hpp"
|
||||||
#include "textured_quad/shader.hpp"
|
#include "textured_quad/shader.hpp"
|
||||||
|
#include "model/shader.hpp"
|
||||||
|
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
@ -23,6 +24,7 @@ struct ShaderState {
|
||||||
colored_quad::State coloredQuad;
|
colored_quad::State coloredQuad;
|
||||||
textured_quad::State texturedQuad;
|
textured_quad::State texturedQuad;
|
||||||
stream::State stream;
|
stream::State stream;
|
||||||
|
model::State model;
|
||||||
};
|
};
|
||||||
struct ShaderDrawCommand {
|
struct ShaderDrawCommand {
|
||||||
ShaderType type;
|
ShaderType type;
|
||||||
|
@ -31,6 +33,7 @@ struct ShaderDrawCommand {
|
||||||
colored_quad::DrawData coloredQuad;
|
colored_quad::DrawData coloredQuad;
|
||||||
textured_quad::DrawData texturedQuad;
|
textured_quad::DrawData texturedQuad;
|
||||||
stream::DrawData stream;
|
stream::DrawData stream;
|
||||||
|
model::DrawData model;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
struct PipelineCreateCommand {
|
struct PipelineCreateCommand {
|
||||||
|
@ -40,6 +43,7 @@ struct PipelineCreateCommand {
|
||||||
colored_quad::PipelineConfig coloredQuad;
|
colored_quad::PipelineConfig coloredQuad;
|
||||||
textured_quad::PipelineConfig texturedQuad;
|
textured_quad::PipelineConfig texturedQuad;
|
||||||
stream::PipelineConfig stream;
|
stream::PipelineConfig stream;
|
||||||
|
model::PipelineConfig model;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
enum class CommandType {
|
enum class CommandType {
|
||||||
|
@ -80,9 +84,11 @@ std::atomic_uint32_t createdPipelines;
|
||||||
static ByteBuffer g_verts;
|
static ByteBuffer g_verts;
|
||||||
static ByteBuffer g_uniforms;
|
static ByteBuffer g_uniforms;
|
||||||
static ByteBuffer g_indices;
|
static ByteBuffer g_indices;
|
||||||
|
static ByteBuffer g_storage;
|
||||||
wgpu::Buffer g_vertexBuffer;
|
wgpu::Buffer g_vertexBuffer;
|
||||||
wgpu::Buffer g_uniformBuffer;
|
wgpu::Buffer g_uniformBuffer;
|
||||||
wgpu::Buffer g_indexBuffer;
|
wgpu::Buffer g_indexBuffer;
|
||||||
|
wgpu::Buffer g_storageBuffer;
|
||||||
|
|
||||||
static ShaderState g_state;
|
static ShaderState g_state;
|
||||||
static PipelineRef g_currentPipeline;
|
static PipelineRef g_currentPipeline;
|
||||||
|
@ -207,6 +213,16 @@ PipelineRef pipeline_ref(stream::PipelineConfig config) {
|
||||||
[=]() { return create_pipeline(g_state.stream, config); });
|
[=]() { return create_pipeline(g_state.stream, config); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
void push_draw_command(model::DrawData data) {
|
||||||
|
push_draw_command({.type = ShaderType::Model, .model = data});
|
||||||
|
}
|
||||||
|
template <>
|
||||||
|
PipelineRef pipeline_ref(model::PipelineConfig config) {
|
||||||
|
return find_pipeline({.type = ShaderType::Model, .model = config},
|
||||||
|
[=]() { return create_pipeline(g_state.model, config); });
|
||||||
|
}
|
||||||
|
|
||||||
static void pipeline_worker() {
|
static void pipeline_worker() {
|
||||||
bool hasMore = false;
|
bool hasMore = false;
|
||||||
while (true) {
|
while (true) {
|
||||||
|
@ -242,34 +258,43 @@ void initialize() {
|
||||||
g_pipelineThread = std::thread(pipeline_worker);
|
g_pipelineThread = std::thread(pipeline_worker);
|
||||||
|
|
||||||
{
|
{
|
||||||
const auto uniformDescriptor = wgpu::BufferDescriptor{
|
const wgpu::BufferDescriptor descriptor{
|
||||||
.label = "Shared Uniform Buffer",
|
.label = "Shared Uniform Buffer",
|
||||||
.usage = wgpu::BufferUsage::Uniform | wgpu::BufferUsage::CopyDst,
|
.usage = wgpu::BufferUsage::Uniform | wgpu::BufferUsage::CopyDst,
|
||||||
.size = 134217728, // 128mb
|
.size = 134217728, // 128mb
|
||||||
};
|
};
|
||||||
g_uniformBuffer = g_device.CreateBuffer(&uniformDescriptor);
|
g_uniformBuffer = g_device.CreateBuffer(&descriptor);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const auto vertexDescriptor = wgpu::BufferDescriptor{
|
const wgpu::BufferDescriptor descriptor{
|
||||||
.label = "Shared Vertex Buffer",
|
.label = "Shared Vertex Buffer",
|
||||||
.usage = wgpu::BufferUsage::Vertex | wgpu::BufferUsage::CopyDst,
|
.usage = wgpu::BufferUsage::Vertex | wgpu::BufferUsage::CopyDst,
|
||||||
.size = 16777216, // 16mb
|
.size = 16777216, // 16mb
|
||||||
};
|
};
|
||||||
g_vertexBuffer = g_device.CreateBuffer(&vertexDescriptor);
|
g_vertexBuffer = g_device.CreateBuffer(&descriptor);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const auto vertexDescriptor = wgpu::BufferDescriptor{
|
const wgpu::BufferDescriptor descriptor{
|
||||||
.label = "Shared Index Buffer",
|
.label = "Shared Index Buffer",
|
||||||
.usage = wgpu::BufferUsage::Vertex | wgpu::BufferUsage::CopyDst,
|
.usage = wgpu::BufferUsage::Index | wgpu::BufferUsage::CopyDst,
|
||||||
.size = 4194304, // 4mb
|
.size = 4194304, // 4mb
|
||||||
};
|
};
|
||||||
g_indexBuffer = g_device.CreateBuffer(&vertexDescriptor);
|
g_indexBuffer = g_device.CreateBuffer(&descriptor);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const wgpu::BufferDescriptor descriptor{
|
||||||
|
.label = "Shared Storage Buffer",
|
||||||
|
.usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopyDst,
|
||||||
|
.size = 134217728, // 128mb
|
||||||
|
};
|
||||||
|
g_storageBuffer = g_device.CreateBuffer(&descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_state.moviePlayer = movie_player::construct_state();
|
g_state.moviePlayer = movie_player::construct_state();
|
||||||
g_state.coloredQuad = colored_quad::construct_state();
|
g_state.coloredQuad = colored_quad::construct_state();
|
||||||
g_state.texturedQuad = textured_quad::construct_state();
|
g_state.texturedQuad = textured_quad::construct_state();
|
||||||
g_state.stream = stream::construct_state();
|
g_state.stream = stream::construct_state();
|
||||||
|
g_state.model = model::construct_state();
|
||||||
}
|
}
|
||||||
|
|
||||||
void shutdown() {
|
void shutdown() {
|
||||||
|
@ -285,6 +310,7 @@ void shutdown() {
|
||||||
g_vertexBuffer = {};
|
g_vertexBuffer = {};
|
||||||
g_uniformBuffer = {};
|
g_uniformBuffer = {};
|
||||||
g_indexBuffer = {};
|
g_indexBuffer = {};
|
||||||
|
g_storageBuffer = {};
|
||||||
|
|
||||||
g_state = {};
|
g_state = {};
|
||||||
}
|
}
|
||||||
|
@ -303,6 +329,10 @@ void render(const wgpu::RenderPassEncoder& pass) {
|
||||||
g_queue.WriteBuffer(g_indexBuffer, 0, g_indices.data(), g_indices.size());
|
g_queue.WriteBuffer(g_indexBuffer, 0, g_indices.data(), g_indices.size());
|
||||||
g_indices.clear();
|
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;
|
||||||
|
@ -336,6 +366,9 @@ void render(const wgpu::RenderPassEncoder& pass) {
|
||||||
case ShaderType::Stream:
|
case ShaderType::Stream:
|
||||||
stream::render(g_state.stream, draw.stream, pass);
|
stream::render(g_state.stream, draw.stream, pass);
|
||||||
break;
|
break;
|
||||||
|
case ShaderType::Model:
|
||||||
|
model::render(g_state.model, draw.model, pass);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
@ -363,10 +396,16 @@ static inline Range push(ByteBuffer& target, const uint8_t* data, size_t length,
|
||||||
padding = alignment - length % alignment;
|
padding = alignment - length % alignment;
|
||||||
}
|
}
|
||||||
auto begin = target.size();
|
auto begin = target.size();
|
||||||
|
if (length == 0) {
|
||||||
|
// TODO shared zero buf?
|
||||||
|
length = alignment;
|
||||||
|
target.append_zeroes(alignment);
|
||||||
|
} else {
|
||||||
target.append(data, length);
|
target.append(data, length);
|
||||||
if (padding > 0) {
|
if (padding > 0) {
|
||||||
target.append_zeroes(padding);
|
target.append_zeroes(padding);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return {begin, begin + length};
|
return {begin, begin + length};
|
||||||
}
|
}
|
||||||
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? */); }
|
||||||
|
@ -376,6 +415,11 @@ Range push_uniform(const uint8_t* data, size_t length) {
|
||||||
g_device.GetLimits(&limits);
|
g_device.GetLimits(&limits);
|
||||||
return push(g_uniforms, data, length, limits.limits.minUniformBufferOffsetAlignment);
|
return push(g_uniforms, data, length, limits.limits.minUniformBufferOffsetAlignment);
|
||||||
}
|
}
|
||||||
|
Range push_storage(const uint8_t* data, size_t length) {
|
||||||
|
wgpu::SupportedLimits limits;
|
||||||
|
g_device.GetLimits(&limits);
|
||||||
|
return push(g_storage, data, length, limits.limits.minStorageBufferOffsetAlignment);
|
||||||
|
}
|
||||||
|
|
||||||
BindGroupRef bind_group_ref(const wgpu::BindGroupDescriptor& descriptor) {
|
BindGroupRef bind_group_ref(const wgpu::BindGroupDescriptor& descriptor) {
|
||||||
const auto id =
|
const auto id =
|
||||||
|
|
|
@ -147,6 +147,7 @@ namespace aurora::gfx {
|
||||||
extern wgpu::Buffer g_vertexBuffer;
|
extern wgpu::Buffer g_vertexBuffer;
|
||||||
extern wgpu::Buffer g_uniformBuffer;
|
extern wgpu::Buffer g_uniformBuffer;
|
||||||
extern wgpu::Buffer g_indexBuffer;
|
extern wgpu::Buffer g_indexBuffer;
|
||||||
|
extern wgpu::Buffer g_storageBuffer;
|
||||||
|
|
||||||
struct TextureRef {
|
struct TextureRef {
|
||||||
wgpu::Texture texture;
|
wgpu::Texture texture;
|
||||||
|
@ -178,6 +179,7 @@ enum class ShaderType {
|
||||||
TexturedQuad,
|
TexturedQuad,
|
||||||
MoviePlayer,
|
MoviePlayer,
|
||||||
Stream,
|
Stream,
|
||||||
|
Model,
|
||||||
};
|
};
|
||||||
|
|
||||||
void initialize();
|
void initialize();
|
||||||
|
@ -200,6 +202,11 @@ template <typename T>
|
||||||
static inline Range push_uniform(const T& data) {
|
static inline Range push_uniform(const T& data) {
|
||||||
return push_uniform(reinterpret_cast<const uint8_t*>(&data), sizeof(T));
|
return push_uniform(reinterpret_cast<const uint8_t*>(&data), sizeof(T));
|
||||||
}
|
}
|
||||||
|
Range push_storage(const uint8_t* data, size_t length);
|
||||||
|
template <typename T>
|
||||||
|
static inline Range push_storage(const T& data) {
|
||||||
|
return push_storage(reinterpret_cast<const uint8_t*>(&data), sizeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename State>
|
template <typename State>
|
||||||
const State& get_state();
|
const State& get_state();
|
||||||
|
|
|
@ -295,7 +295,7 @@ wgpu::RenderPipeline build_pipeline(const PipelineConfig& config, const ShaderIn
|
||||||
.targetCount = colorTargets.size(),
|
.targetCount = colorTargets.size(),
|
||||||
.targets = colorTargets.data(),
|
.targets = colorTargets.data(),
|
||||||
};
|
};
|
||||||
const auto layouts = build_bind_group_layouts(info);
|
const auto layouts = build_bind_group_layouts(info, config.shaderConfig);
|
||||||
const std::array bindGroupLayouts{
|
const std::array bindGroupLayouts{
|
||||||
layouts.uniformLayout,
|
layouts.uniformLayout,
|
||||||
layouts.samplerLayout,
|
layouts.samplerLayout,
|
||||||
|
@ -328,7 +328,7 @@ wgpu::RenderPipeline build_pipeline(const PipelineConfig& config, const ShaderIn
|
||||||
return g_device.CreateRenderPipeline(&descriptor);
|
return g_device.CreateRenderPipeline(&descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderInfo populate_pipeline_config(PipelineConfig& config, GX::Primitive primitive) noexcept {
|
ShaderInfo populate_pipeline_config(PipelineConfig& config, GX::Primitive primitive, const BindGroupRanges& ranges) noexcept {
|
||||||
for (size_t idx = 0; const auto& item : g_tevStages) {
|
for (size_t idx = 0; const auto& item : g_tevStages) {
|
||||||
// Copy until disabled TEV stage (indicating end)
|
// Copy until disabled TEV stage (indicating end)
|
||||||
if (!item) {
|
if (!item) {
|
||||||
|
@ -357,7 +357,7 @@ ShaderInfo populate_pipeline_config(PipelineConfig& config, GX::Primitive primit
|
||||||
{
|
{
|
||||||
std::lock_guard lk{g_pipelineMutex};
|
std::lock_guard lk{g_pipelineMutex};
|
||||||
auto [_, info] = build_shader(config.shaderConfig);
|
auto [_, info] = build_shader(config.shaderConfig);
|
||||||
info.bindGroups = build_bind_groups(info); // TODO this is hack
|
info.bindGroups = build_bind_groups(info, config.shaderConfig, ranges); // TODO this is hack
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -398,15 +398,42 @@ Range build_uniform(const ShaderInfo& info) noexcept {
|
||||||
static std::unordered_map<u32, wgpu::BindGroupLayout> sUniformBindGroupLayouts;
|
static std::unordered_map<u32, wgpu::BindGroupLayout> sUniformBindGroupLayouts;
|
||||||
static std::unordered_map<u32, std::pair<wgpu::BindGroupLayout, wgpu::BindGroupLayout>> sTextureBindGroupLayouts;
|
static std::unordered_map<u32, std::pair<wgpu::BindGroupLayout, wgpu::BindGroupLayout>> sTextureBindGroupLayouts;
|
||||||
|
|
||||||
GXBindGroups build_bind_groups(const ShaderInfo& info) noexcept {
|
GXBindGroups build_bind_groups(const ShaderInfo& info, const ShaderConfig& config,
|
||||||
const auto layouts = build_bind_group_layouts(info);
|
const BindGroupRanges& ranges) noexcept {
|
||||||
|
const auto layouts = build_bind_group_layouts(info, config);
|
||||||
u32 textureCount = info.sampledTextures.count();
|
u32 textureCount = info.sampledTextures.count();
|
||||||
|
|
||||||
const std::array uniformEntries{wgpu::BindGroupEntry{
|
const std::array uniformEntries{
|
||||||
|
wgpu::BindGroupEntry{
|
||||||
.binding = 0,
|
.binding = 0,
|
||||||
.buffer = g_uniformBuffer,
|
.buffer = g_uniformBuffer,
|
||||||
.size = info.uniformSize,
|
.size = info.uniformSize,
|
||||||
}};
|
},
|
||||||
|
// Vertices
|
||||||
|
wgpu::BindGroupEntry{
|
||||||
|
.binding = 1,
|
||||||
|
.buffer = g_storageBuffer,
|
||||||
|
.size = ranges.vtxDataRange.second - ranges.vtxDataRange.first,
|
||||||
|
},
|
||||||
|
// Normals
|
||||||
|
wgpu::BindGroupEntry{
|
||||||
|
.binding = 2,
|
||||||
|
.buffer = g_storageBuffer,
|
||||||
|
.size = ranges.nrmDataRange.second - ranges.nrmDataRange.first,
|
||||||
|
},
|
||||||
|
// UVs
|
||||||
|
wgpu::BindGroupEntry{
|
||||||
|
.binding = 3,
|
||||||
|
.buffer = g_storageBuffer,
|
||||||
|
.size = ranges.tcDataRange.second - ranges.tcDataRange.first,
|
||||||
|
},
|
||||||
|
// Packed UVs
|
||||||
|
wgpu::BindGroupEntry{
|
||||||
|
.binding = 4,
|
||||||
|
.buffer = g_storageBuffer,
|
||||||
|
.size = ranges.packedTcDataRange.second - ranges.packedTcDataRange.first,
|
||||||
|
},
|
||||||
|
};
|
||||||
std::array<wgpu::BindGroupEntry, maxTextures> samplerEntries;
|
std::array<wgpu::BindGroupEntry, maxTextures> samplerEntries;
|
||||||
std::array<wgpu::BindGroupEntry, maxTextures> textureEntries;
|
std::array<wgpu::BindGroupEntry, maxTextures> textureEntries;
|
||||||
for (u32 texIdx = 0, i = 0; texIdx < info.sampledTextures.size(); ++texIdx) {
|
for (u32 texIdx = 0, i = 0; texIdx < info.sampledTextures.size(); ++texIdx) {
|
||||||
|
@ -432,7 +459,7 @@ GXBindGroups build_bind_groups(const ShaderInfo& info) noexcept {
|
||||||
.uniformBindGroup = bind_group_ref(wgpu::BindGroupDescriptor{
|
.uniformBindGroup = bind_group_ref(wgpu::BindGroupDescriptor{
|
||||||
.label = "GX Uniform Bind Group",
|
.label = "GX Uniform Bind Group",
|
||||||
.layout = layouts.uniformLayout,
|
.layout = layouts.uniformLayout,
|
||||||
.entryCount = uniformEntries.size(),
|
.entryCount = static_cast<uint32_t>(config.denormalizedVertexAttributes ? 1 : uniformEntries.size()),
|
||||||
.entries = uniformEntries.data(),
|
.entries = uniformEntries.data(),
|
||||||
}),
|
}),
|
||||||
.samplerBindGroup = bind_group_ref(wgpu::BindGroupDescriptor{
|
.samplerBindGroup = bind_group_ref(wgpu::BindGroupDescriptor{
|
||||||
|
@ -450,12 +477,14 @@ GXBindGroups build_bind_groups(const ShaderInfo& info) noexcept {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
GXBindGroupLayouts build_bind_group_layouts(const ShaderInfo& info) noexcept {
|
GXBindGroupLayouts build_bind_group_layouts(const ShaderInfo& info, const ShaderConfig& config) noexcept {
|
||||||
GXBindGroupLayouts out;
|
GXBindGroupLayouts out;
|
||||||
if (sUniformBindGroupLayouts.contains(info.uniformSize)) {
|
u32 uniformSizeKey = info.uniformSize + (config.denormalizedVertexAttributes ? 0 : 1);
|
||||||
out.uniformLayout = sUniformBindGroupLayouts[info.uniformSize];
|
if (sUniformBindGroupLayouts.contains(uniformSizeKey)) {
|
||||||
|
out.uniformLayout = sUniformBindGroupLayouts[uniformSizeKey];
|
||||||
} else {
|
} else {
|
||||||
const std::array uniformLayoutEntries{wgpu::BindGroupLayoutEntry{
|
const std::array uniformLayoutEntries{
|
||||||
|
wgpu::BindGroupLayoutEntry{
|
||||||
.binding = 0,
|
.binding = 0,
|
||||||
.visibility = wgpu::ShaderStage::Vertex | wgpu::ShaderStage::Fragment,
|
.visibility = wgpu::ShaderStage::Vertex | wgpu::ShaderStage::Fragment,
|
||||||
.buffer =
|
.buffer =
|
||||||
|
@ -464,14 +493,51 @@ GXBindGroupLayouts build_bind_group_layouts(const ShaderInfo& info) noexcept {
|
||||||
.hasDynamicOffset = true,
|
.hasDynamicOffset = true,
|
||||||
.minBindingSize = info.uniformSize,
|
.minBindingSize = info.uniformSize,
|
||||||
},
|
},
|
||||||
}};
|
},
|
||||||
|
wgpu::BindGroupLayoutEntry{
|
||||||
|
.binding = 1,
|
||||||
|
.visibility = wgpu::ShaderStage::Vertex,
|
||||||
|
.buffer =
|
||||||
|
{
|
||||||
|
.type = wgpu::BufferBindingType::ReadOnlyStorage,
|
||||||
|
.hasDynamicOffset = true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wgpu::BindGroupLayoutEntry{
|
||||||
|
.binding = 2,
|
||||||
|
.visibility = wgpu::ShaderStage::Vertex,
|
||||||
|
.buffer =
|
||||||
|
{
|
||||||
|
.type = wgpu::BufferBindingType::ReadOnlyStorage,
|
||||||
|
.hasDynamicOffset = true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wgpu::BindGroupLayoutEntry{
|
||||||
|
.binding = 3,
|
||||||
|
.visibility = wgpu::ShaderStage::Vertex,
|
||||||
|
.buffer =
|
||||||
|
{
|
||||||
|
.type = wgpu::BufferBindingType::ReadOnlyStorage,
|
||||||
|
.hasDynamicOffset = true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wgpu::BindGroupLayoutEntry{
|
||||||
|
.binding = 4,
|
||||||
|
.visibility = wgpu::ShaderStage::Vertex,
|
||||||
|
.buffer =
|
||||||
|
{
|
||||||
|
.type = wgpu::BufferBindingType::ReadOnlyStorage,
|
||||||
|
.hasDynamicOffset = true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
const auto uniformLayoutDescriptor = wgpu::BindGroupLayoutDescriptor{
|
const auto uniformLayoutDescriptor = wgpu::BindGroupLayoutDescriptor{
|
||||||
.label = "GX Uniform Bind Group Layout",
|
.label = "GX Uniform Bind Group Layout",
|
||||||
.entryCount = uniformLayoutEntries.size(),
|
.entryCount = static_cast<uint32_t>(config.denormalizedVertexAttributes ? 1 : uniformLayoutEntries.size()),
|
||||||
.entries = uniformLayoutEntries.data(),
|
.entries = uniformLayoutEntries.data(),
|
||||||
};
|
};
|
||||||
out.uniformLayout = g_device.CreateBindGroupLayout(&uniformLayoutDescriptor);
|
out.uniformLayout = g_device.CreateBindGroupLayout(&uniformLayoutDescriptor);
|
||||||
sUniformBindGroupLayouts.try_emplace(info.uniformSize, out.uniformLayout);
|
sUniformBindGroupLayouts.try_emplace(uniformSizeKey, out.uniformLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 textureCount = info.sampledTextures.count();
|
u32 textureCount = info.sampledTextures.count();
|
||||||
|
|
|
@ -77,8 +77,9 @@ const TextureBind& get_texture(GX::TexMapID id) noexcept;
|
||||||
struct ShaderConfig {
|
struct ShaderConfig {
|
||||||
std::array<std::optional<STevStage>, maxTevStages> tevStages;
|
std::array<std::optional<STevStage>, maxTevStages> tevStages;
|
||||||
std::array<GX::ColorSrc, 2> channelMatSrcs;
|
std::array<GX::ColorSrc, 2> channelMatSrcs;
|
||||||
bool alphaDiscard;
|
bool alphaDiscard = false;
|
||||||
bool denormalizedVertexAttributes;
|
bool denormalizedVertexAttributes = false;
|
||||||
|
bool denormalizedHasNrm = false; // TODO this is a hack
|
||||||
};
|
};
|
||||||
struct PipelineConfig {
|
struct PipelineConfig {
|
||||||
ShaderConfig shaderConfig;
|
ShaderConfig shaderConfig;
|
||||||
|
@ -111,15 +112,33 @@ struct ShaderInfo {
|
||||||
bool usesVtxColor : 1 = false;
|
bool usesVtxColor : 1 = false;
|
||||||
bool usesNormal : 1 = false;
|
bool usesNormal : 1 = false;
|
||||||
};
|
};
|
||||||
ShaderInfo populate_pipeline_config(PipelineConfig& config, GX::Primitive primitive) noexcept;
|
struct BindGroupRanges {
|
||||||
|
Range vtxDataRange;
|
||||||
|
Range nrmDataRange;
|
||||||
|
Range tcDataRange;
|
||||||
|
Range packedTcDataRange;
|
||||||
|
};
|
||||||
|
ShaderInfo populate_pipeline_config(PipelineConfig& config, GX::Primitive primitive,
|
||||||
|
const BindGroupRanges& ranges) noexcept;
|
||||||
wgpu::RenderPipeline build_pipeline(const PipelineConfig& config, const ShaderInfo& info,
|
wgpu::RenderPipeline build_pipeline(const PipelineConfig& config, const ShaderInfo& info,
|
||||||
ArrayRef<wgpu::VertexBufferLayout> vtxBuffers, wgpu::ShaderModule shader,
|
ArrayRef<wgpu::VertexBufferLayout> vtxBuffers, wgpu::ShaderModule shader,
|
||||||
zstring_view label) noexcept;
|
zstring_view label) noexcept;
|
||||||
std::pair<wgpu::ShaderModule, ShaderInfo> build_shader(const ShaderConfig& config) noexcept;
|
std::pair<wgpu::ShaderModule, ShaderInfo> build_shader(const ShaderConfig& config) noexcept;
|
||||||
// Range build_vertex_buffer(const GXShaderInfo& info) noexcept;
|
// Range build_vertex_buffer(const GXShaderInfo& info) noexcept;
|
||||||
Range build_uniform(const ShaderInfo& info) noexcept;
|
Range build_uniform(const ShaderInfo& info) noexcept;
|
||||||
GXBindGroupLayouts build_bind_group_layouts(const ShaderInfo& info) noexcept;
|
GXBindGroupLayouts build_bind_group_layouts(const ShaderInfo& info, const ShaderConfig& config) noexcept;
|
||||||
GXBindGroups build_bind_groups(const ShaderInfo& info) noexcept;
|
GXBindGroups build_bind_groups(const ShaderInfo& info, const ShaderConfig& config,
|
||||||
|
const BindGroupRanges& ranges) noexcept;
|
||||||
|
|
||||||
|
struct DlVert {
|
||||||
|
s16 pos;
|
||||||
|
s16 norm;
|
||||||
|
// colors ignored
|
||||||
|
std::array<s16, 7> uvs;
|
||||||
|
// pn_mtx_idx ignored
|
||||||
|
// tex_mtx_idxs ignored
|
||||||
|
s16 _pad;
|
||||||
|
};
|
||||||
} // namespace aurora::gfx::gx
|
} // namespace aurora::gfx::gx
|
||||||
|
|
||||||
namespace aurora {
|
namespace aurora {
|
||||||
|
@ -149,6 +168,7 @@ inline XXH64_hash_t xxh3_hash(const gfx::gx::ShaderConfig& input, XXH64_hash_t s
|
||||||
XXH3_64bits_update(&state, input.channelMatSrcs.data(), input.channelMatSrcs.size() * sizeof(GX::ColorSrc));
|
XXH3_64bits_update(&state, input.channelMatSrcs.data(), input.channelMatSrcs.size() * sizeof(GX::ColorSrc));
|
||||||
XXH3_64bits_update(&state, &input.alphaDiscard, sizeof(bool));
|
XXH3_64bits_update(&state, &input.alphaDiscard, sizeof(bool));
|
||||||
XXH3_64bits_update(&state, &input.denormalizedVertexAttributes, sizeof(bool));
|
XXH3_64bits_update(&state, &input.denormalizedVertexAttributes, sizeof(bool));
|
||||||
|
XXH3_64bits_update(&state, &input.denormalizedHasNrm, sizeof(bool));
|
||||||
return XXH3_64bits_digest(&state);
|
return XXH3_64bits_digest(&state);
|
||||||
}
|
}
|
||||||
} // namespace aurora
|
} // namespace aurora
|
|
@ -315,6 +315,10 @@ 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{
|
||||||
|
.uniformSize = 64, // MVP MTX
|
||||||
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
for (int i = 0; i < config.tevStages.size(); ++i) {
|
for (int i = 0; i < config.tevStages.size(); ++i) {
|
||||||
const auto& stage = config.tevStages[i];
|
const auto& stage = config.tevStages[i];
|
||||||
|
@ -354,22 +358,49 @@ std::pair<wgpu::ShaderModule, ShaderInfo> build_shader(const ShaderConfig& confi
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string uniBufAttrs;
|
std::string uniBufAttrs;
|
||||||
|
std::string uniformBindings;
|
||||||
std::string sampBindings;
|
std::string sampBindings;
|
||||||
std::string texBindings;
|
std::string texBindings;
|
||||||
std::string vtxOutAttrs;
|
std::string vtxOutAttrs;
|
||||||
std::string vtxInAttrs;
|
std::string vtxInAttrs;
|
||||||
|
std::string vtxXfrAttrsPre;
|
||||||
std::string vtxXfrAttrs;
|
std::string vtxXfrAttrs;
|
||||||
size_t locIdx = 0;
|
size_t locIdx = 0;
|
||||||
// TODO
|
if (config.denormalizedVertexAttributes) {
|
||||||
// if (config.denormalizedNorm) {
|
vtxInAttrs += "\n @location(0) in_pos: vec3<f32>";
|
||||||
// vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) nrm: vec3<f32>;"), locIdx);
|
vtxOutAttrs += "\n @builtin(position) pos: vec4<f32>;";
|
||||||
// vtxInAttrs += fmt::format(FMT_STRING("\n , @location({}) in_nrm: vec3<f32>"), ++locIdx);
|
vtxXfrAttrsPre += "\n out.pos = ubuf.xf * vec4<f32>(in_pos, 1.0);";
|
||||||
// vtxXfrAttrs += fmt::format(FMT_STRING("\n out.nrm = in_nrm;"));
|
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;"));
|
||||||
|
info.usesNormal = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uniformBindings += R"""(
|
||||||
|
struct Vec3Block {
|
||||||
|
data: array<vec3<f32>>;
|
||||||
|
};
|
||||||
|
struct Vec2Block {
|
||||||
|
data: array<vec2<f32>>;
|
||||||
|
};
|
||||||
|
@group(0) @binding(1)
|
||||||
|
var<storage, read> v_verts: Vec3Block;
|
||||||
|
@group(0) @binding(2)
|
||||||
|
var<storage, read> v_norms: Vec3Block;
|
||||||
|
@group(0) @binding(3)
|
||||||
|
var<storage, read> v_uvs: Vec2Block;
|
||||||
|
@group(0) @binding(4)
|
||||||
|
var<storage, read> v_packed_uvs: Vec2Block;
|
||||||
|
)""";
|
||||||
|
vtxInAttrs +=
|
||||||
|
"\n @location(0) in_pos_nrm_idx: vec2<i32>"
|
||||||
|
"\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]], 1.0);";
|
||||||
|
}
|
||||||
|
|
||||||
ShaderInfo info{
|
|
||||||
.uniformSize = 64, // MVP MTX
|
|
||||||
};
|
|
||||||
std::string fragmentFnPre;
|
std::string fragmentFnPre;
|
||||||
std::string fragmentFn;
|
std::string fragmentFn;
|
||||||
for (size_t idx = 0; const auto& stage : config.tevStages) {
|
for (size_t idx = 0; const auto& stage : config.tevStages) {
|
||||||
|
@ -432,7 +463,7 @@ std::pair<wgpu::ShaderModule, ShaderInfo> build_shader(const ShaderConfig& confi
|
||||||
}
|
}
|
||||||
fragmentFnPre += fmt::format(FMT_STRING("\n var rast{} = in.clr; // TODO lighting"), i);
|
fragmentFnPre += fmt::format(FMT_STRING("\n var rast{} = in.clr; // TODO lighting"), i);
|
||||||
} else {
|
} else {
|
||||||
Log.report(logvisor::Fatal, FMT_STRING("Don't know how to do this yet")); // TODO
|
Log.report(logvisor::Fatal, FMT_STRING("SRC_VTX unsupported with normalized vertex attributes"));
|
||||||
}
|
}
|
||||||
info.usesVtxColor = true;
|
info.usesVtxColor = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -465,7 +496,16 @@ std::pair<wgpu::ShaderModule, ShaderInfo> build_shader(const ShaderConfig& confi
|
||||||
vtxInAttrs += fmt::format(FMT_STRING("\n , @location({}) in_tex{}_uv: vec2<f32>"), locIdx + 1, i);
|
vtxInAttrs += fmt::format(FMT_STRING("\n , @location({}) in_tex{}_uv: vec2<f32>"), locIdx + 1, i);
|
||||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n out.tex{0}_uv = in_tex{0}_uv;"), i);
|
vtxXfrAttrs += fmt::format(FMT_STRING("\n out.tex{0}_uv = in_tex{0}_uv;"), i);
|
||||||
} else {
|
} else {
|
||||||
Log.report(logvisor::Fatal, FMT_STRING("Don't know how to do this yet")); // TODO
|
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) tex{}_uv: vec2<f32>;"), locIdx, i);
|
||||||
|
if (i < 4) {
|
||||||
|
if (i == 0) {
|
||||||
|
vtxXfrAttrs += fmt::format(FMT_STRING("\n out.tex{}_uv = v_packed_uvs.data[in_uv_0_4[{}]];"), i, i);
|
||||||
|
} else {
|
||||||
|
vtxXfrAttrs += fmt::format(FMT_STRING("\n out.tex{}_uv = v_uvs.data[in_uv_0_4[{}]];"), i, i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
vtxXfrAttrs += fmt::format(FMT_STRING("\n out.tex{}_uv = v_uvs.data[in_uv_5_7[{}]];"), i, i - 4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
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, in.tex{0}_uv, ubuf.tex{0}_lod);"), i);
|
||||||
|
@ -478,18 +518,15 @@ struct Uniform {{
|
||||||
xf: mat4x4<f32>;{uniBufAttrs}
|
xf: mat4x4<f32>;{uniBufAttrs}
|
||||||
}};
|
}};
|
||||||
@group(0) @binding(0)
|
@group(0) @binding(0)
|
||||||
var<uniform> ubuf: Uniform;{sampBindings}{texBindings}
|
var<uniform> ubuf: Uniform;{uniformBindings}{sampBindings}{texBindings}
|
||||||
|
|
||||||
struct VertexOutput {{
|
struct VertexOutput {{{vtxOutAttrs}
|
||||||
@builtin(position) pos: vec4<f32>;{vtxOutAttrs}
|
|
||||||
}};
|
}};
|
||||||
|
|
||||||
@stage(vertex)
|
@stage(vertex)
|
||||||
fn vs_main(
|
fn vs_main({vtxInAttrs}
|
||||||
@location(0) in_pos: vec3<f32>{vtxInAttrs}
|
|
||||||
) -> VertexOutput {{
|
) -> VertexOutput {{
|
||||||
var out: VertexOutput;
|
var out: VertexOutput;{vtxXfrAttrsPre}{vtxXfrAttrs}
|
||||||
out.pos = ubuf.xf * vec4<f32>(in_pos, 1.0);{vtxXfrAttrs}
|
|
||||||
return out;
|
return out;
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
@ -501,7 +538,8 @@ 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);
|
"fragmentFn"_a = fragmentFn, "fragmentFnPre"_a = fragmentFnPre, "vtxXfrAttrsPre"_a = vtxXfrAttrsPre,
|
||||||
|
"uniformBindings"_a = uniformBindings);
|
||||||
Log.report(logvisor::Info, FMT_STRING("Generated shader: {}"), shaderSource);
|
Log.report(logvisor::Info, FMT_STRING("Generated shader: {}"), shaderSource);
|
||||||
|
|
||||||
wgpu::ShaderModuleWGSLDescriptor wgslDescriptor{};
|
wgpu::ShaderModuleWGSLDescriptor wgslDescriptor{};
|
||||||
|
|
|
@ -59,16 +59,6 @@ void set_normal_buffer(const std::vector<zeus::CVector3f>& norm) noexcept { nrmD
|
||||||
void set_tex0_tc_buffer(const std::vector<zeus::CVector2f>& tcs) noexcept { tex0TcData = &tcs; }
|
void set_tex0_tc_buffer(const std::vector<zeus::CVector2f>& tcs) noexcept { tex0TcData = &tcs; }
|
||||||
void set_tc_buffer(const std::vector<zeus::CVector2f>& tcs) noexcept { tcData = &tcs; }
|
void set_tc_buffer(const std::vector<zeus::CVector2f>& tcs) noexcept { tcData = &tcs; }
|
||||||
|
|
||||||
struct DlVert {
|
|
||||||
s16 pos;
|
|
||||||
s16 norm;
|
|
||||||
// colors ignored
|
|
||||||
std::array<s16, 7> uvs;
|
|
||||||
// pn_mtx_idx ignored
|
|
||||||
// tex_mtx_idxs ignored
|
|
||||||
s16 _pad;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class VertexFormat : u8 {
|
enum class VertexFormat : u8 {
|
||||||
F32F32,
|
F32F32,
|
||||||
S16F32,
|
S16F32,
|
||||||
|
@ -77,8 +67,8 @@ enum class VertexFormat : u8 {
|
||||||
static VtxDescFlags sVtxDescFlags;
|
static VtxDescFlags sVtxDescFlags;
|
||||||
void set_vtx_desc_compressed(u32 vtxDesc) noexcept { sVtxDescFlags = vtxDesc; }
|
void set_vtx_desc_compressed(u32 vtxDesc) noexcept { sVtxDescFlags = vtxDesc; }
|
||||||
|
|
||||||
static inline std::pair<DlVert, size_t> readVert(const u8* data) noexcept {
|
static inline std::pair<gx::DlVert, size_t> readVert(const u8* data) noexcept {
|
||||||
DlVert out{};
|
gx::DlVert out{};
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
const auto read8 = [data, &offset](VtxDescAttrType type) -> s8 {
|
const auto read8 = [data, &offset](VtxDescAttrType type) -> s8 {
|
||||||
if (type == VtxDescAttrType::Direct) {
|
if (type == VtxDescAttrType::Direct) {
|
||||||
|
@ -122,7 +112,7 @@ static inline std::pair<DlVert, size_t> readVert(const u8* data) noexcept {
|
||||||
|
|
||||||
void queue_surface(const u8* dlStart, u32 dlSize) noexcept {
|
void queue_surface(const u8* dlStart, u32 dlSize) noexcept {
|
||||||
// Log.report(logvisor::Info, FMT_STRING("DL size {}"), dlSize);
|
// Log.report(logvisor::Info, FMT_STRING("DL size {}"), dlSize);
|
||||||
std::vector<DlVert> verts;
|
std::vector<gx::DlVert> verts;
|
||||||
std::vector<u32> indices;
|
std::vector<u32> indices;
|
||||||
|
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
|
@ -176,5 +166,70 @@ void queue_surface(const u8* dlStart, u32 dlSize) noexcept {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log.report(logvisor::Info, FMT_STRING("Read {} verts, {} indices"), verts.size(), indices.size());
|
// Log.report(logvisor::Info, FMT_STRING("Read {} verts, {} indices"), verts.size(), indices.size());
|
||||||
|
const auto vertRange = push_verts(ArrayRef{verts});
|
||||||
|
const auto idxRange = push_indices(ArrayRef{indices});
|
||||||
|
const auto sVtxRange = push_storage(reinterpret_cast<const uint8_t*>(vtxData->data()), vtxData->size() * 16);
|
||||||
|
const auto sNrmRange = push_storage(reinterpret_cast<const uint8_t*>(nrmData->data()), nrmData->size() * 16);
|
||||||
|
const auto sTcRange = push_storage(reinterpret_cast<const uint8_t*>(tcData->data()), tcData->size() * 16);
|
||||||
|
Range sPackedTcRange;
|
||||||
|
if (tcData == tex0TcData) {
|
||||||
|
sPackedTcRange = sTcRange;
|
||||||
|
} else {
|
||||||
|
sPackedTcRange = push_storage(reinterpret_cast<const uint8_t*>(tex0TcData->data()), tex0TcData->size() * 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
model::PipelineConfig config{};
|
||||||
|
const gx::BindGroupRanges ranges{
|
||||||
|
.vtxDataRange = sVtxRange,
|
||||||
|
.nrmDataRange = sNrmRange,
|
||||||
|
.tcDataRange = sTcRange,
|
||||||
|
.packedTcDataRange = sPackedTcRange,
|
||||||
|
};
|
||||||
|
const auto info = populate_pipeline_config(config, GX::TRIANGLES, ranges);
|
||||||
|
const auto pipeline = pipeline_ref(config);
|
||||||
|
|
||||||
|
push_draw_command(model::DrawData{
|
||||||
|
.pipeline = pipeline,
|
||||||
|
.vertRange = vertRange,
|
||||||
|
.idxRange = idxRange,
|
||||||
|
.sVtxRange = sVtxRange,
|
||||||
|
.sNrmRange = sNrmRange,
|
||||||
|
.sTcRange = sTcRange,
|
||||||
|
.sPackedTcRange = sPackedTcRange,
|
||||||
|
.uniformRange = build_uniform(info),
|
||||||
|
.indexCount = static_cast<uint32_t>(indices.size()),
|
||||||
|
.bindGroups = info.bindGroups,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
State construct_state() { return {}; }
|
||||||
|
|
||||||
|
wgpu::RenderPipeline create_pipeline(const State& state, [[maybe_unused]] PipelineConfig config) {
|
||||||
|
const auto [shader, info] = build_shader(config.shaderConfig);
|
||||||
|
|
||||||
|
const auto attributes = gpu::utils::make_vertex_attributes(
|
||||||
|
std::array{wgpu::VertexFormat::Sint16x2, wgpu::VertexFormat::Sint16x4, wgpu::VertexFormat::Sint16x4});
|
||||||
|
const std::array vertexBuffers{gpu::utils::make_vertex_buffer_layout(sizeof(gx::DlVert), attributes)};
|
||||||
|
|
||||||
|
return build_pipeline(config, info, vertexBuffers, shader, "Model Pipeline");
|
||||||
|
}
|
||||||
|
|
||||||
|
void render(const State& state, const DrawData& data, const wgpu::RenderPassEncoder& pass) {
|
||||||
|
if (!bind_pipeline(data.pipeline, pass)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::array offsets{
|
||||||
|
data.uniformRange.first, data.sVtxRange.first, data.sNrmRange.first,
|
||||||
|
data.sTcRange.first, data.sPackedTcRange.first,
|
||||||
|
};
|
||||||
|
pass.SetBindGroup(0, find_bind_group(data.bindGroups.uniformBindGroup), offsets.size(), offsets.data());
|
||||||
|
if (data.bindGroups.samplerBindGroup && data.bindGroups.textureBindGroup) {
|
||||||
|
pass.SetBindGroup(1, find_bind_group(data.bindGroups.samplerBindGroup));
|
||||||
|
pass.SetBindGroup(2, find_bind_group(data.bindGroups.textureBindGroup));
|
||||||
|
}
|
||||||
|
pass.SetVertexBuffer(0, g_vertexBuffer, data.vertRange.first, data.vertRange.second);
|
||||||
|
pass.SetIndexBuffer(g_indexBuffer, wgpu::IndexFormat::Uint32, data.idxRange.first, data.idxRange.second);
|
||||||
|
pass.DrawIndexed(data.indexCount);
|
||||||
}
|
}
|
||||||
} // namespace aurora::gfx::model
|
} // namespace aurora::gfx::model
|
||||||
|
|
|
@ -9,16 +9,18 @@ namespace aurora::gfx::model {
|
||||||
struct DrawData {
|
struct DrawData {
|
||||||
PipelineRef pipeline;
|
PipelineRef pipeline;
|
||||||
Range vertRange;
|
Range vertRange;
|
||||||
|
Range idxRange;
|
||||||
|
Range sVtxRange;
|
||||||
|
Range sNrmRange;
|
||||||
|
Range sTcRange;
|
||||||
|
Range sPackedTcRange;
|
||||||
Range uniformRange;
|
Range uniformRange;
|
||||||
uint32_t vertexCount;
|
uint32_t indexCount;
|
||||||
uint32_t uniformSize;
|
gx::GXBindGroups bindGroups;
|
||||||
BindGroupRef samplerBindGroup;
|
|
||||||
BindGroupRef textureBindGroup;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PipelineConfig : gx::PipelineConfig {
|
struct PipelineConfig : gx::PipelineConfig {
|
||||||
ShaderRef shader;
|
|
||||||
uint32_t uniformSize;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CachedBindGroup {
|
struct CachedBindGroup {
|
||||||
|
@ -28,10 +30,6 @@ struct CachedBindGroup {
|
||||||
: layout(std::move(layout)), bindGroup(std::move(group)) {}
|
: layout(std::move(layout)), bindGroup(std::move(group)) {}
|
||||||
};
|
};
|
||||||
struct State {
|
struct State {
|
||||||
wgpu::BindGroupLayout samplerLayout;
|
|
||||||
wgpu::BindGroupLayout textureLayout;
|
|
||||||
mutable std::unordered_map<uint32_t, CachedBindGroup> uniform;
|
|
||||||
mutable std::unordered_map<uint64_t, wgpu::Sampler> sampler;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
State construct_state();
|
State construct_state();
|
||||||
|
|
|
@ -59,7 +59,8 @@ void stream_end() noexcept {
|
||||||
|
|
||||||
stream::PipelineConfig config{};
|
stream::PipelineConfig config{};
|
||||||
config.shaderConfig.denormalizedVertexAttributes = true;
|
config.shaderConfig.denormalizedVertexAttributes = true;
|
||||||
const auto info = populate_pipeline_config(config, sStreamState->primitive);
|
config.shaderConfig.denormalizedHasNrm = sStreamState->flags.IsSet(metaforce::EStreamFlagBits::fHasNormal);
|
||||||
|
const auto info = populate_pipeline_config(config, sStreamState->primitive, {});
|
||||||
const auto pipeline = pipeline_ref(config);
|
const auto pipeline = pipeline_ref(config);
|
||||||
|
|
||||||
push_draw_command(stream::DrawData{
|
push_draw_command(stream::DrawData{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#if defined(__x86_64__) || defined(__i386__) || defined(_M_IX86) || defined(_M_X64)
|
//#if defined(__x86_64__) || defined(__i386__) || defined(_M_IX86) || defined(_M_X64)
|
||||||
#include "xxh_x86dispatch.c"
|
//#include "xxh_x86dispatch.c"
|
||||||
#endif
|
//#endif
|
||||||
#include "xxhash.c"
|
#include "xxhash.c"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#if defined(__x86_64__) || defined(__i386__) || defined(_M_IX86) || defined(_M_X64)
|
//#if defined(__x86_64__) || defined(__i386__) || defined(_M_IX86) || defined(_M_X64)
|
||||||
#include "xxh_x86dispatch.h"
|
//#include "xxh_x86dispatch.h"
|
||||||
#else
|
//#else
|
||||||
#include "xxhash.h"
|
#include "xxhash.h"
|
||||||
#endif
|
//#endif
|
||||||
|
|
Loading…
Reference in New Issue