Adds texture matrix tests.

This commit is contained in:
Erik Abair 2022-03-11 08:21:17 -08:00
parent d977dd0450
commit 89632200f8
10 changed files with 294 additions and 4 deletions

View File

@ -38,6 +38,7 @@ SRCS = \
$(SRCDIR)/tests/test_suite.cpp \
$(SRCDIR)/tests/texture_border_tests.cpp \
$(SRCDIR)/tests/texture_format_tests.cpp \
$(SRCDIR)/tests/texture_matrix_tests.cpp \
$(SRCDIR)/tests/texture_render_target_tests.cpp \
$(SRCDIR)/tests/three_d_primitive_tests.cpp \
$(SRCDIR)/tests/two_d_line_tests.cpp \

View File

@ -30,6 +30,7 @@
#include "tests/set_vertex_data_tests.h"
#include "tests/texture_border_tests.h"
#include "tests/texture_format_tests.h"
#include "tests/texture_matrix_tests.h"
#include "tests/texture_render_target_tests.h"
#include "tests/three_d_primitive_tests.h"
#include "tests/two_d_line_tests.h"
@ -205,6 +206,10 @@ static void register_suites(TestHost& host, std::vector<std::shared_ptr<TestSuit
auto suite = std::make_shared<TextureFormatTests>(host, output_directory);
test_suites.push_back(std::dynamic_pointer_cast<TestSuite>(suite));
}
{
auto suite = std::make_shared<TextureMatrixTests>(host, output_directory);
test_suites.push_back(std::dynamic_pointer_cast<TestSuite>(suite));
}
{
auto suite = std::make_shared<TextureRenderTargetTests>(host, output_directory);
test_suites.push_back(std::dynamic_pointer_cast<TestSuite>(suite));

View File

@ -134,6 +134,32 @@ uint32_t *pb_push_4x3_matrix(uint32_t *p, DWORD command, const float *m) {
return p;
}
uint32_t *pb_push_4x4_matrix(uint32_t *p, DWORD command, const float *m) {
pb_push_to(SUBCH_3D, p++, command, 16);
*((float *)p++) = m[_11];
*((float *)p++) = m[_12];
*((float *)p++) = m[_13];
*((float *)p++) = m[_14];
*((float *)p++) = m[_21];
*((float *)p++) = m[_22];
*((float *)p++) = m[_23];
*((float *)p++) = m[_24];
*((float *)p++) = m[_31];
*((float *)p++) = m[_32];
*((float *)p++) = m[_33];
*((float *)p++) = m[_34];
*((float *)p++) = m[_41];
*((float *)p++) = m[_42];
*((float *)p++) = m[_43];
*((float *)p++) = m[_44];
return p;
}
void pb_print_with_floats(const char *format, ...) {
char buffer[512];

View File

@ -73,6 +73,9 @@ void* pb_agp_access(void* fb_memory_pointer);
// not transposed).
uint32_t* pb_push_4x3_matrix(uint32_t* p, DWORD command, const float* m);
// Pushes a 4x4 matrix (not transposed).
uint32_t* pb_push_4x4_matrix(uint32_t* p, DWORD command, const float* m);
uint32_t* pb_push1f(uint32_t* p, DWORD command, float param1);
uint32_t* pb_push2f(uint32_t* p, DWORD command, float param1, float param2);
uint32_t* pb_push3f(uint32_t* p, DWORD command, float param1, float param2, float param3);

View File

@ -105,6 +105,8 @@ void TestSuite::Initialize() {
p = pb_begin();
p = pb_push1(p, NV097_SET_SHADER_STAGE_PROGRAM, 0x0);
MATRIX identity_matrix;
matrix_unit(identity_matrix);
for (auto i = 0; i < 4; ++i) {
auto& stage = host_.GetTextureStage(i);
stage.SetUWrap(TextureStage::WRAP_CLAMP_TO_EDGE, false);
@ -117,6 +119,9 @@ void TestSuite::Initialize() {
stage.SetFilter();
stage.SetAlphaKillEnable(false);
stage.SetLODClamp(0, 4095);
stage.SetTextureMatrixEnable(false);
stage.SetTextureMatrix(identity_matrix);
}
// TODO: Set up with TextureStage instances in host_.
@ -164,6 +169,10 @@ void TestSuite::Initialize() {
p = pb_push1(p, NV097_SET_STENCIL_MASK, true);
p = pb_push1(p, NV097_SET_NORMALIZATION_ENABLE, false);
p = pb_push1(p, NV097_SET_TEXGEN_S, NV097_SET_TEXGEN_S_DISABLE);
p = pb_push1(p, NV097_SET_TEXGEN_T, NV097_SET_TEXGEN_S_DISABLE);
p = pb_push1(p, NV097_SET_TEXGEN_R, NV097_SET_TEXGEN_S_DISABLE);
pb_end(p);
host_.SetDefaultViewportAndFixedFunctionMatrices();

View File

@ -0,0 +1,205 @@
#include "texture_matrix_tests.h"
#include <SDL.h>
#include <pbkit/pbkit.h>
#include <memory>
#include <utility>
#include "debug_output.h"
#include "pbkit_ext.h"
#include "test_host.h"
#include "texture_format.h"
#include "vertex_buffer.h"
static int GenerateSurface(SDL_Surface **surface, int width, int height);
static constexpr int kTextureWidth = 256;
static constexpr int kTextureHeight = 128;
TextureMatrixTests::TextureMatrixTests(TestHost &host, std::string output_dir)
: TestSuite(host, std::move(output_dir), "Texture Matrix") {
{
constexpr char kTestName[] = "Identity";
tests_[kTestName] = [this, kTestName]() {
MATRIX matrix;
matrix_unit(matrix);
Test(kTestName, matrix);
};
}
{
constexpr char kTestName[] = "Double";
tests_[kTestName] = [this, kTestName]() {
MATRIX matrix;
matrix_unit(matrix);
VECTOR scale = {2.0, 2.0, 2.0, 1.0};
matrix_scale(matrix, matrix, scale);
Test(kTestName, matrix);
};
}
{
constexpr char kTestName[] = "Half";
tests_[kTestName] = [this, kTestName]() {
MATRIX matrix;
matrix_unit(matrix);
VECTOR scale = {0.5, 0.5, 0.5, 1.0};
matrix_scale(matrix, matrix, scale);
Test(kTestName, matrix);
};
}
{
constexpr char kTestName[] = "ShiftHPlus";
tests_[kTestName] = [this, kTestName]() {
MATRIX matrix;
matrix_unit(matrix);
VECTOR translate = {0.5, 0.0, 0.0, 0.0};
matrix_translate(matrix, matrix, translate);
Test(kTestName, matrix);
};
}
{
constexpr char kTestName[] = "ShiftHMinus";
tests_[kTestName] = [this, kTestName]() {
MATRIX matrix;
matrix_unit(matrix);
VECTOR translate = {-0.5, 0.0, 0.0, 0.0};
matrix_translate(matrix, matrix, translate);
Test(kTestName, matrix);
};
}
{
constexpr char kTestName[] = "ShiftVPlus";
tests_[kTestName] = [this, kTestName]() {
MATRIX matrix;
matrix_unit(matrix);
VECTOR translate = {0.0, 0.5, 0.0, 0.0};
matrix_translate(matrix, matrix, translate);
Test(kTestName, matrix);
};
}
{
constexpr char kTestName[] = "ShiftVMinus";
tests_[kTestName] = [this, kTestName]() {
MATRIX matrix;
matrix_unit(matrix);
VECTOR translate = {0.0, -0.5, 0.0, 0.0};
matrix_translate(matrix, matrix, translate);
Test(kTestName, matrix);
};
}
{
constexpr char kTestName[] = "RotateX";
tests_[kTestName] = [this, kTestName]() {
MATRIX matrix;
matrix_unit(matrix);
VECTOR rot = {M_PI * 0.5, 0.0, 0.0, 0.0};
matrix_rotate(matrix, matrix, rot);
Test(kTestName, matrix);
};
}
{
constexpr char kTestName[] = "RotateY";
tests_[kTestName] = [this, kTestName]() {
MATRIX matrix;
matrix_unit(matrix);
VECTOR rot = {0.0, M_PI * 0.5, 0.0, 0.0};
matrix_rotate(matrix, matrix, rot);
Test(kTestName, matrix);
};
}
{
constexpr char kTestName[] = "RotateZ";
tests_[kTestName] = [this, kTestName]() {
MATRIX matrix;
matrix_unit(matrix);
VECTOR rot = {0.0, 0.0, M_PI * 0.5, 0.0};
matrix_rotate(matrix, matrix, rot);
Test(kTestName, matrix);
};
}
}
void TextureMatrixTests::Initialize() {
TestSuite::Initialize();
CreateGeometry();
host_.SetXDKDefaultViewportAndFixedFunctionMatrices();
host_.SetTextureStageEnabled(0, true);
host_.SetShaderStageProgram(TestHost::STAGE_2D_PROJECTIVE);
host_.SetTextureFormat(GetTextureFormatInfo(NV097_SET_TEXTURE_FORMAT_COLOR_SZ_R8G8B8A8));
{
auto &texture_stage = host_.GetTextureStage(0);
texture_stage.SetBorderColor(0xFF7F007F);
texture_stage.SetTextureDimensions(kTextureWidth, kTextureHeight);
texture_stage.SetTextureMatrixEnable(true);
}
SDL_Surface *gradient_surface;
int update_texture_result = GenerateSurface(&gradient_surface, kTextureWidth, kTextureHeight);
ASSERT(!update_texture_result && "Failed to generate SDL surface");
update_texture_result = host_.SetTexture(gradient_surface, 0);
SDL_FreeSurface(gradient_surface);
ASSERT(!update_texture_result && "Failed to set texture");
host_.SetCombinerControl(1, true, true);
host_.SetFinalCombiner0Just(TestHost::SRC_TEX0);
host_.SetFinalCombiner1Just(TestHost::SRC_ZERO, true, true);
}
void TextureMatrixTests::CreateGeometry() {
static constexpr float left = -2.75f;
static constexpr float right = 2.75f;
static constexpr float top = 1.0f;
static constexpr float bottom = -2.5f;
std::shared_ptr<VertexBuffer> buffer = host_.AllocateVertexBuffer(6);
buffer->DefineBiTri(0, left, top, right, bottom);
}
void TextureMatrixTests::Test(const char *test_name, MATRIX matrix) {
host_.PrepareDraw(0xFE202020);
auto &texture_stage = host_.GetTextureStage(0);
texture_stage.SetTextureMatrix(matrix);
host_.SetupTextureStages();
host_.DrawArrays();
pb_print("%s\n", test_name);
const float *val = matrix;
for (auto i = 0; i < 4; ++i, val += 4) {
pb_print_with_floats("%.3f %.3f %.3f %.3f\n", val[0], val[1], val[2], val[3]);
}
pb_draw_text_screen();
host_.FinishDraw(allow_saving_, output_dir_, test_name);
}
static int GenerateSurface(SDL_Surface **surface, int width, int height) {
*surface = SDL_CreateRGBSurfaceWithFormat(0, width, height, 32, SDL_PIXELFORMAT_RGBA8888);
if (!(*surface)) {
return 1;
}
if (SDL_LockSurface(*surface)) {
SDL_FreeSurface(*surface);
*surface = nullptr;
return 2;
}
auto pixels = static_cast<uint32_t *>((*surface)->pixels);
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x, ++pixels) {
int x_normal = static_cast<int>(static_cast<float>(x) * 255.0f / static_cast<float>(width));
int y_normal = static_cast<int>(static_cast<float>(y) * 255.0f / static_cast<float>(height));
*pixels = SDL_MapRGBA((*surface)->format, y_normal, x_normal, 255 - y_normal, x_normal + y_normal);
}
}
SDL_UnlockSurface(*surface);
return 0;
}

View File

@ -0,0 +1,24 @@
#ifndef NXDK_PGRAPH_TESTS_TEXTURE_MATRIX_TESTS_H
#define NXDK_PGRAPH_TESTS_TEXTURE_MATRIX_TESTS_H
#include <memory>
#include <string>
#include "test_host.h"
#include "test_suite.h"
struct TextureFormatInfo;
class VertexBuffer;
class TextureMatrixTests : public TestSuite {
public:
TextureMatrixTests(TestHost &host, std::string output_dir);
void Initialize() override;
private:
void CreateGeometry();
void Test(const char *test_name, MATRIX matrix);
};
#endif // NXDK_PGRAPH_TESTS_TEXTURE_MATRIX_TESTS_H

View File

@ -8,11 +8,9 @@
#include "debug_output.h"
#include "pbkit_ext.h"
#include "shaders/perspective_vertex_shader.h"
#include "shaders/precalculated_vertex_shader.h"
#include "test_host.h"
#include "texture_format.h"
#include "vertex_buffer.h"
#define SET_MASK(mask, val) (((val) << (__builtin_ffs(mask) - 1)) & (mask))

View File

@ -1,12 +1,17 @@
#include "texture_stage.h"
#include "debug_output.h"
#include "math3d.h"
#include "nxdk_ext.h"
#include "pbkit_ext.h"
#include "swizzle.h"
// bitscan forward
static int bsf(int val) { __asm bsf eax, val }
static int bsf(int val){__asm bsf eax, val}
TextureStage::TextureStage() {
matrix_unit(texture_matrix_);
}
bool TextureStage::RequiresColorspaceConversion() const {
return format_.xbox_format == NV097_SET_TEXTURE_FORMAT_COLOR_LC_IMAGE_CR8YB8CB8YA8 ||
@ -103,7 +108,10 @@ void TextureStage::Commit(uint32_t memory_dma_offset, uint32_t palette_dma_offse
bump_env_material[3]);
p = pb_push1f(p, NV097_SET_TEXTURE_SET_BUMP_ENV_SCALE, bump_env_scale);
p = pb_push1f(p, NV097_SET_TEXTURE_SET_BUMP_ENV_OFFSET, bump_env_offset);
p = pb_push1(p, NV097_SET_TEXTURE_MATRIX_ENABLE + (4 * stage_), texture_matrix_enable_);
if (texture_matrix_enable_) {
p = pb_push_4x4_matrix(p, NV097_SET_TEXTURE_MATRIX + 64 * stage_, texture_matrix_);
}
pb_end(p);
}

View File

@ -33,6 +33,8 @@ class TextureStage {
enum WrapMode { WRAP_REPEAT = 1, WRAP_MIRROR, WRAP_CLAMP_TO_EDGE, WRAP_BORDER, WRAP_CLAMP_TO_EDGE_OGL };
public:
TextureStage();
void SetUWrap(WrapMode mode, bool cylinder_wrap = false) {
wrap_modes_[0] = mode;
cylinder_wrap_[0] = cylinder_wrap;
@ -101,6 +103,12 @@ class TextureStage {
bool IsLinear() const { return format_.xbox_linear; }
bool RequiresColorspaceConversion() const;
void SetTextureMatrixEnable(bool enabled) { texture_matrix_enable_ = enabled; }
bool GetTextureMatrixEnable() const { return texture_matrix_enable_; }
void SetTextureMatrix(const float *matrix) { memcpy(texture_matrix_, matrix, sizeof(texture_matrix_)); }
const float *GetTextureMatrix() const { return texture_matrix_; }
float *GetTextureMatrix() { return texture_matrix_; }
private:
friend class TestHost;
@ -152,6 +160,9 @@ class TextureStage {
float bump_env_material[4] = {0.0f, 0.0f, 0.0f, 0.0f};
float bump_env_scale{0.0f};
float bump_env_offset{0.0f};
bool texture_matrix_enable_{false};
float texture_matrix_[16];
};
#endif // NXDK_PGRAPH_TESTS_TEXTURE_STAGE_H