- Start work on drawlist
- Fix issue in texloader - add ivec2 to tecloader / screen - add draw func for iron - add bufCfg in 3 variants to c3d - add poc for c3d_permutation
This commit is contained in:
@@ -19,7 +19,8 @@ add_library(${PROJECT_NAME} STATIC
|
|||||||
source/utils.cpp
|
source/utils.cpp
|
||||||
source/c3d.cpp
|
source/c3d.cpp
|
||||||
source/ctru.cpp
|
source/ctru.cpp
|
||||||
source/iron.cpp
|
source/iron/iron.cpp
|
||||||
|
source/iron/drawlist.cpp
|
||||||
source/maths/mat.cpp
|
source/maths/mat.cpp
|
||||||
)
|
)
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC include)
|
target_include_directories(${PROJECT_NAME} PUBLIC include)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include <amethyst/asset.hpp>
|
#include <amethyst/asset.hpp>
|
||||||
#include <amethyst/maths/mat.hpp>
|
#include <amethyst/maths/mat.hpp>
|
||||||
|
#include <amethyst/maths/vec.hpp>
|
||||||
#include <amethyst/types.hpp>
|
#include <amethyst/types.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -26,6 +27,7 @@ class c3d {
|
|||||||
|
|
||||||
int width() const { return m_width; }
|
int width() const { return m_width; }
|
||||||
int height() const { return m_height; }
|
int height() const { return m_height; }
|
||||||
|
ivec2 size() const { return ivec2(m_width, m_height); }
|
||||||
void clear() { C3D_RenderTargetClear(m_target, C3D_CLEAR_ALL, 0, 0); }
|
void clear() { C3D_RenderTargetClear(m_target, C3D_CLEAR_ALL, 0, 0); }
|
||||||
void startDraw() { C3D_FrameDrawOn(m_target); }
|
void startDraw() { C3D_FrameDrawOn(m_target); }
|
||||||
|
|
||||||
@@ -83,5 +85,57 @@ class c3d {
|
|||||||
GPU_Primitive_t prim = GPU_TRIANGLES);
|
GPU_Primitive_t prim = GPU_TRIANGLES);
|
||||||
static void drawElements(int count, const void* idx_ptr, int type = GPU_SHORT,
|
static void drawElements(int count, const void* idx_ptr, int type = GPU_SHORT,
|
||||||
GPU_Primitive_t prim = GPU_TRIANGLES);
|
GPU_Primitive_t prim = GPU_TRIANGLES);
|
||||||
|
static void depthTest(bool on, GPU_TESTFUNC func = GPU_GREATER,
|
||||||
|
GPU_WRITEMASK mask = GPU_WRITE_ALL);
|
||||||
|
static void disableScissor();
|
||||||
|
static void enableScissor(const ivec4 rect);
|
||||||
|
/**
|
||||||
|
* Buf cfg die permutation at runtime berechnet
|
||||||
|
*/
|
||||||
|
static void bufCfg(void* ptr, int stride, int shader_attribs);
|
||||||
|
/**
|
||||||
|
* Klassische config bei der man selber die permutation eintragen muss
|
||||||
|
*/
|
||||||
|
static void bufCfg(void* ptr, int stride, int shader_attribs,
|
||||||
|
u64 permutation);
|
||||||
|
/**
|
||||||
|
* Hacky funktion um die permutation automatisch at compile time zu berechnen,
|
||||||
|
* falls diese immer gleich bleibt.
|
||||||
|
* In der <> steht die anzahl der shader input werte
|
||||||
|
* usage: c3d::bufCfg<3>(data, sizeof(vertex));
|
||||||
|
*/
|
||||||
|
template <int attribs>
|
||||||
|
constexpr static void bufCfg(void* ptr, int stride) {
|
||||||
|
auto buf = C3D_GetBufInfo();
|
||||||
|
BufInfo_Init(buf);
|
||||||
|
constexpr int pm = permutation(attribs);
|
||||||
|
BufInfo_Add(buf, ptr, stride, attribs, pm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int drawcalls() { return m_drawcalls; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
static int m_drawcalls;
|
||||||
|
static int m__dc__;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Funktion die anhand von **ac** genau den permu station wert für BufInfo
|
||||||
|
* ausrechnet wie z.B
|
||||||
|
* ```
|
||||||
|
* ac = 3 -> 0x210
|
||||||
|
* ac = 4 -> 0x3210
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
constexpr static u64 permutation(int ac) {
|
||||||
|
u64 ret = 0;
|
||||||
|
if (ac < 1 || ac > 15) {
|
||||||
|
throw std::runtime_error("[amy] " + std::to_string(ac) +
|
||||||
|
" is out of range (1...15)!");
|
||||||
|
}
|
||||||
|
for (int i = 0; i < ac; i++) {
|
||||||
|
ret = (ret << 4) | (ac - 1 - i);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} // namespace amy
|
} // namespace amy
|
||||||
@@ -26,6 +26,7 @@ class iron {
|
|||||||
u32 color = 0;
|
u32 color = 0;
|
||||||
};
|
};
|
||||||
class command {
|
class command {
|
||||||
|
public:
|
||||||
command() = default;
|
command() = default;
|
||||||
using ref = up<command>;
|
using ref = up<command>;
|
||||||
command& add(const u16& idx) {
|
command& add(const u16& idx) {
|
||||||
@@ -58,7 +59,7 @@ class iron {
|
|||||||
|
|
||||||
void merge(drawlist* list);
|
void merge(drawlist* list);
|
||||||
command::ref newCommand();
|
command::ref newCommand();
|
||||||
void push(commad* cmd);
|
void push(command ::ref cmd);
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
void drawSolid();
|
void drawSolid();
|
||||||
@@ -74,7 +75,7 @@ class iron {
|
|||||||
static void init();
|
static void init();
|
||||||
static void newFrame();
|
static void newFrame();
|
||||||
static void drawOn(c3d::screen* screen);
|
static void drawOn(c3d::screen* screen);
|
||||||
static void draw(const std::vector<command>& data);
|
static void draw(const std::vector<command::ref>& data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void setupShader();
|
static void setupShader();
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include <amethyst/asset.hpp>
|
#include <amethyst/asset.hpp>
|
||||||
#include <amethyst/image.hpp>
|
#include <amethyst/image.hpp>
|
||||||
|
#include <amethyst/types.hpp>
|
||||||
|
|
||||||
namespace amy {
|
namespace amy {
|
||||||
class texture : public asset {
|
class texture : public asset {
|
||||||
@@ -14,17 +15,20 @@ class texture : public asset {
|
|||||||
void load(cstr& path);
|
void load(cstr& path);
|
||||||
void unload();
|
void unload();
|
||||||
|
|
||||||
int w() const { return m_w; }
|
int w() const { return m_size.x; }
|
||||||
int& w() { return m_w; }
|
int& w() { return m_size.x; }
|
||||||
int h() const { return m_h; }
|
int h() const { return m_size.y; }
|
||||||
int& h() { return m_h; }
|
int& h() { return m_size.y; }
|
||||||
|
ivec2 size() const { return m_size; }
|
||||||
|
ivec2& size() { return m_size; }
|
||||||
|
|
||||||
C3D_Tex* getTex() { return m_loaded ? &m_tex : nullptr; }
|
C3D_Tex* ptr() { return m_loaded ? &m_tex : nullptr; }
|
||||||
|
|
||||||
|
void bind(int reg = 0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
C3D_Tex m_tex;
|
C3D_Tex m_tex;
|
||||||
int m_w = 0;
|
ivec2 m_size;
|
||||||
int m_h = 0;
|
|
||||||
bool m_loaded = false;
|
bool m_loaded = false;
|
||||||
};
|
};
|
||||||
} // namespace amy
|
} // namespace amy
|
||||||
@@ -1,7 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <amethyst/maths/vec.hpp>
|
||||||
|
#include <cinttypes>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|||||||
3
poc/CMakeLists.txt
Normal file
3
poc/CMakeLists.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.22)
|
||||||
|
|
||||||
|
add_subdirectory(c3d_permutation)
|
||||||
3
poc/README.md
Normal file
3
poc/README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Proof of concepts
|
||||||
|
|
||||||
|
This folder contains some proof of concept tests.
|
||||||
8
poc/c3d_permutation/CMakeLists.txt
Normal file
8
poc/c3d_permutation/CMakeLists.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.22)
|
||||||
|
|
||||||
|
project(c3d-permutation)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED true)
|
||||||
|
|
||||||
|
add_executable(c3d-permutation source/main.cpp)
|
||||||
10
poc/c3d_permutation/README.md
Normal file
10
poc/c3d_permutation/README.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# Citro3D Shader Buf info Permutation calculation
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Why do
|
||||||
|
BufInfo_Add(buf, data, sizeof(data[0]), 3, 0x210);
|
||||||
|
BufInfo_Add(buf, data, sizeof(data[0]), 4, 0x3210);
|
||||||
|
// if we can do
|
||||||
|
BufInfo_Add(buf, data, sizeof(data[0]), 3, permutation(3));
|
||||||
|
BufInfo_Add(buf, data, sizeof(data[0]), 3, permutation(4));
|
||||||
|
```
|
||||||
30
poc/c3d_permutation/source/main.cpp
Normal file
30
poc/c3d_permutation/source/main.cpp
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#include <format>
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
using u64 = unsigned long long;
|
||||||
|
|
||||||
|
constexpr u64 permutation(int ac) {
|
||||||
|
u64 ret = 0;
|
||||||
|
if (ac < 1 || ac > 15) {
|
||||||
|
throw std::runtime_error("[amy] " + std::to_string(ac) +
|
||||||
|
" is out of range (1...15)!");
|
||||||
|
}
|
||||||
|
for (int i = 0; i < ac; i++) {
|
||||||
|
ret = (ret << 4) | (ac - 1 - i);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
int v = 3;
|
||||||
|
if (argc == 2) {
|
||||||
|
v = std::stoi(argv[1]);
|
||||||
|
} else {
|
||||||
|
std::cout << "No input provided! using example..." << std::endl;
|
||||||
|
}
|
||||||
|
std::cout << std::format("{} -> {:#x} ({})", v, permutation(v),
|
||||||
|
permutation(v))
|
||||||
|
<< std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -12,6 +12,8 @@ const auto DISPLAY_TRANSFER_FLAGS =
|
|||||||
GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) |
|
GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) |
|
||||||
GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO);
|
GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO);
|
||||||
C3D_TexEnv* c3d::frag::m_env = nullptr;
|
C3D_TexEnv* c3d::frag::m_env = nullptr;
|
||||||
|
int c3d::m_drawcalls = 0;
|
||||||
|
int c3d::m__dc__ = 0;
|
||||||
|
|
||||||
void c3d::init() { C3D_Init(C3D_DEFAULT_CMDBUF_SIZE); }
|
void c3d::init() { C3D_Init(C3D_DEFAULT_CMDBUF_SIZE); }
|
||||||
|
|
||||||
@@ -19,9 +21,13 @@ void c3d::deinit() { C3D_Fini(); }
|
|||||||
|
|
||||||
void c3d::startFrame(bool sync) {
|
void c3d::startFrame(bool sync) {
|
||||||
C3D_FrameBegin(sync ? C3D_FRAME_SYNCDRAW : C3D_FRAME_NONBLOCK);
|
C3D_FrameBegin(sync ? C3D_FRAME_SYNCDRAW : C3D_FRAME_NONBLOCK);
|
||||||
|
m__dc__ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void c3d::endFrame() { C3D_FrameEnd(0); }
|
void c3d::endFrame() {
|
||||||
|
C3D_FrameEnd(0);
|
||||||
|
m_drawcalls = m__dc__;
|
||||||
|
}
|
||||||
|
|
||||||
c3d::screen* c3d::createScreen(gfxScreen_t screen, gfx3dSide_t side) {
|
c3d::screen* c3d::createScreen(gfxScreen_t screen, gfx3dSide_t side) {
|
||||||
auto t = C3D_RenderTargetCreate(240, screen == GFX_TOP ? 400 : 320,
|
auto t = C3D_RenderTargetCreate(240, screen == GFX_TOP ? 400 : 320,
|
||||||
@@ -39,7 +45,8 @@ c3d::shader::~shader() {}
|
|||||||
void c3d::shader::load(const std::string& path) {
|
void c3d::shader::load(const std::string& path) {
|
||||||
auto code = utils::loadFile2Mem(path);
|
auto code = utils::loadFile2Mem(path);
|
||||||
if (!code.size()) {
|
if (!code.size()) {
|
||||||
throw std::runtime_error("[amy] shader: unable to load " + path);
|
throw std::runtime_error(
|
||||||
|
std::format("[amy] unsable to load shader ({})", path));
|
||||||
}
|
}
|
||||||
load(code);
|
load(code);
|
||||||
}
|
}
|
||||||
@@ -58,6 +65,10 @@ void c3d::shader::compile(const std::string& code) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void c3d::shader::use() {
|
void c3d::shader::use() {
|
||||||
|
C3D_BindProgram(&m_program);
|
||||||
|
// for some reason i need both ???
|
||||||
|
// code works perfectly without C3D_BindProgram
|
||||||
|
// but nor withour shaderProgramUse ...
|
||||||
shaderProgramUse(&m_program);
|
shaderProgramUse(&m_program);
|
||||||
C3D_SetAttrInfo(&m_info);
|
C3D_SetAttrInfo(&m_info);
|
||||||
}
|
}
|
||||||
@@ -92,10 +103,32 @@ void c3d::frag::edit(int id) {
|
|||||||
|
|
||||||
void c3d::drawArrays(int start, int count, GPU_Primitive_t prim) {
|
void c3d::drawArrays(int start, int count, GPU_Primitive_t prim) {
|
||||||
C3D_DrawArrays(prim, start, count);
|
C3D_DrawArrays(prim, start, count);
|
||||||
|
m__dc__++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void c3d::drawElements(int count, const void* idx_ptr, int type,
|
void c3d::drawElements(int count, const void* idx_ptr, int type,
|
||||||
GPU_Primitive_t prim) {
|
GPU_Primitive_t prim) {
|
||||||
C3D_DrawElements(prim, count, type, idx_ptr);
|
C3D_DrawElements(prim, count, type, idx_ptr);
|
||||||
|
m__dc__++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void c3d::depthTest(bool on, GPU_TESTFUNC func, GPU_WRITEMASK mask) {
|
||||||
|
C3D_DepthTest(on, func, mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
void c3d::disableScissor() { C3D_SetScissor(GPU_SCISSOR_DISABLE, 0, 0, 0, 0); }
|
||||||
|
|
||||||
|
void c3d::enableScissor(const ivec4 rect) {
|
||||||
|
C3D_SetScissor(GPU_SCISSOR_NORMAL, rect.x, rect.y, rect.z, rect.w);
|
||||||
|
}
|
||||||
|
|
||||||
|
void c3d::bufCfg(void* ptr, int stride, int shader_attribs, u64 permutation) {
|
||||||
|
auto buf = C3D_GetBufInfo();
|
||||||
|
BufInfo_Init(buf);
|
||||||
|
BufInfo_Add(buf, ptr, stride, shader_attribs, permutation);
|
||||||
|
}
|
||||||
|
|
||||||
|
void c3d::bufCfg(void* ptr, int stride, int shader_attribs) {
|
||||||
|
bufCfg(ptr, stride, shader_attribs, permutation(shader_attribs));
|
||||||
}
|
}
|
||||||
} // namespace amy
|
} // namespace amy
|
||||||
5
source/iron/drawlist.cpp
Normal file
5
source/iron/drawlist.cpp
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#include <amethyst/iron.hpp>
|
||||||
|
|
||||||
|
namespace amy {
|
||||||
|
void iron::drawlist::merge(iron::drawlist* list) {}
|
||||||
|
} // namespace amy
|
||||||
@@ -60,6 +60,41 @@ void iron::drawOn(c3d::screen* screen) {
|
|||||||
m_shader->setMat4(uLocProj, m_mtx);
|
m_shader->setMat4(uLocProj, m_mtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void iron::draw(const std::vector<iron::command::ref>& data) {
|
||||||
|
// disable depthtest cause we have no z buffer
|
||||||
|
c3d::depthTest(false);
|
||||||
|
fragConfig();
|
||||||
|
size_t i = 0;
|
||||||
|
while (i < data.size()) {
|
||||||
|
texture* tex = data[i]->tex;
|
||||||
|
if (!tex) {
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto scissorOn = data[i]->scissorOn;
|
||||||
|
auto scissor = data[i]->scissorRect;
|
||||||
|
auto start = i;
|
||||||
|
// Loop until a statgechange and copy all data into vertex/index buf
|
||||||
|
while (i < data.size() && scissorOn == data[i]->scissorOn &&
|
||||||
|
scissor == data[i]->scissorRect && tex == data[i]->tex) {
|
||||||
|
auto c = data[i].get();
|
||||||
|
for (int j = 0; j < c->indexBuf.size(); j++) {
|
||||||
|
m_ibuf[m_idx++] = m_vtx + c->indexBuf[i];
|
||||||
|
}
|
||||||
|
for (int j = 0; j < c->vertexBuf.size(); j++) {
|
||||||
|
m_vbuf[m_vtx++] = c->vertexBuf[i];
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
///// SCISSOR LOGIC BEG /////
|
||||||
|
///// SCISSOR LOGIC END /////
|
||||||
|
tex->bind();
|
||||||
|
c3d::bufCfg<3>(m_vbuf.data(), sizeof(vertex));
|
||||||
|
c3d::drawElements(i - start, m_ibuf.data() + start);
|
||||||
|
}
|
||||||
|
c3d::depthTest(true);
|
||||||
|
}
|
||||||
|
|
||||||
void iron::setupShader() {
|
void iron::setupShader() {
|
||||||
m_shader = new c3d::shader();
|
m_shader = new c3d::shader();
|
||||||
m_shader->compile(__ironshader__);
|
m_shader->compile(__ironshader__);
|
||||||
@@ -51,24 +51,24 @@ void texture::load(cstr& path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int bpp = img.bpp();
|
int bpp = img.bpp();
|
||||||
m_w = img.width();
|
m_size.x = img.width();
|
||||||
if (utils::isSingleBitNum(m_w)) {
|
if (utils::isSingleBitNum(m_size.x)) {
|
||||||
m_w = utils::nextPow2(m_w);
|
m_size.x = utils::nextPow2(m_size.x);
|
||||||
}
|
}
|
||||||
m_h = img.width();
|
m_size.y = img.height();
|
||||||
if (utils::isSingleBitNum(m_h)) {
|
if (utils::isSingleBitNum(m_size.y)) {
|
||||||
m_h = utils::nextPow2(m_h);
|
m_size.y = utils::nextPow2(m_size.y);
|
||||||
}
|
}
|
||||||
auto filter = GPU_NEAREST;
|
auto filter = GPU_NEAREST;
|
||||||
auto format = image2TexFmt(img.fmt());
|
auto format = image2TexFmt(img.fmt());
|
||||||
C3D_TexInit(&m_tex, (u16)m_w, (u16)m_h, format);
|
C3D_TexInit(&m_tex, (u16)m_size.x, (u16)m_size.y, format);
|
||||||
C3D_TexSetFilter(&m_tex, filter, filter);
|
C3D_TexSetFilter(&m_tex, filter, filter);
|
||||||
// Using std::fill_n instead cause i hate this error lines
|
// Using std::fill_n instead cause i hate this error lines
|
||||||
// under the memset func in my editor
|
// under the memset func in my editor
|
||||||
std::fill_n((unsigned char*)m_tex.data, m_tex.size, 0);
|
std::fill_n((unsigned char*)m_tex.data, m_tex.size, 0);
|
||||||
for (int x = 0; x < img.width(); x++) {
|
for (int x = 0; x < img.width(); x++) {
|
||||||
for (int y = 0; y < img.height(); y++) {
|
for (int y = 0; y < img.height(); y++) {
|
||||||
int dst_pos = tile3dsTex(x, y, m_w) * bpp;
|
int dst_pos = tile3dsTex(x, y, m_size.x) * bpp;
|
||||||
int src_pos = (y * img.width() + x) * bpp;
|
int src_pos = (y * img.width() + x) * bpp;
|
||||||
/// Best idea i had
|
/// Best idea i had
|
||||||
for (int i = 0; i < bpp; i++) {
|
for (int i = 0; i < bpp; i++) {
|
||||||
@@ -81,4 +81,6 @@ void texture::load(cstr& path) {
|
|||||||
C3D_TexSetWrap(&m_tex, GPU_REPEAT, GPU_REPEAT);
|
C3D_TexSetWrap(&m_tex, GPU_REPEAT, GPU_REPEAT);
|
||||||
m_loaded = true;
|
m_loaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void texture::bind(int reg) { C3D_TexBind(reg, &m_tex); }
|
||||||
} // namespace amy
|
} // namespace amy
|
||||||
Reference in New Issue
Block a user