mirror of
https://github.com/xemu-project/nxdk_pgraph_tests.git
synced 2025-02-17 00:27:44 +00:00
Adds 0x1D78 Z_MIN_MAX_CONTROL tests. (#123)
This commit is contained in:
parent
add9f6ccec
commit
20ed7289ae
@ -146,6 +146,7 @@ generate_nv2a_vshinc_files(
|
||||
src/shaders/fog_vec4_z.vsh
|
||||
src/shaders/fog_vec4_zw.vsh
|
||||
src/shaders/fog_vec4_unset.vsh
|
||||
src/shaders/passthrough.vsh
|
||||
)
|
||||
|
||||
generate_pixelshader_inl_files(
|
||||
@ -366,6 +367,8 @@ add_executable(
|
||||
src/tests/w_param_tests.h
|
||||
src/tests/window_clip_tests.cpp
|
||||
src/tests/window_clip_tests.h
|
||||
src/tests/z_min_max_control_tests.cpp
|
||||
src/tests/z_min_max_control_tests.h
|
||||
src/tests/zero_stride_tests.cpp
|
||||
src/tests/zero_stride_tests.h
|
||||
${generated_vertex_shaders}
|
||||
|
41
README.md
41
README.md
@ -120,6 +120,47 @@ Assuming that this project has been checked out at `/development/pgraph_tester`:
|
||||
the test. You may wish to utilize some of the helper methods from `TestHost`
|
||||
and similar classes rather than using the raw output to improve readability.
|
||||
|
||||
### Writing nv2a vertex shaders in assembly
|
||||
|
||||
See [the README in the nv2a_vsh_asm repository](https://github.com/abaire/nv2a_vsh_asm) for an overview.
|
||||
|
||||
`*.vsh` files are assembed via the `generate_nv2a_vshinc_files` function in CMakeLists.txt. Each vsh file produces a
|
||||
corresponding `.vshinc` file that contains a C-style list of 32-bit integers containing the vertex shader operations.
|
||||
This file is intended to be included from test source files to initialize a constant array which may then be used to
|
||||
populate a `VertexShaderProgram` via `SetShaderOverride`.
|
||||
|
||||
For example:
|
||||
|
||||
```c++
|
||||
// Note that the VertexShaderProgram does not copy this data, so it is important that it remain in scope throughout
|
||||
// the use of the VertexShaderProgram object.
|
||||
static const uint32_t kPassthroughVsh[] = {
|
||||
#include "passthrough.vshinc"
|
||||
};
|
||||
|
||||
// ...
|
||||
|
||||
auto shader = std::make_shared<VertexShaderProgram>();
|
||||
shader->SetShaderOverride(kPassthroughVsh, sizeof(kPassthroughVsh));
|
||||
host_.SetVertexShaderProgram(shader);
|
||||
|
||||
```
|
||||
|
||||
Uniform values may then be set via the `VertexShaderProgram::SetUniform*` series of functions. By default, the 0th
|
||||
uniform will be available in the shader as `c96`.
|
||||
|
||||
For example, a shader that takes a 4-element vertex might have the code:
|
||||
|
||||
```asm
|
||||
#vertex vector 96
|
||||
```
|
||||
|
||||
which would be populated via
|
||||
|
||||
```c++
|
||||
shader->shader->SetUniformF(0, -1.f, 1.5f, 0.f, 1.f);
|
||||
```
|
||||
|
||||
## Running with CLion
|
||||
|
||||
### On xemu
|
||||
|
@ -86,6 +86,7 @@
|
||||
#include "tests/volume_texture_tests.h"
|
||||
#include "tests/w_param_tests.h"
|
||||
#include "tests/window_clip_tests.h"
|
||||
#include "tests/z_min_max_control_tests.h"
|
||||
#include "tests/zero_stride_tests.h"
|
||||
|
||||
#ifndef FALLBACK_OUTPUT_ROOT_PATH
|
||||
@ -679,6 +680,10 @@ static void register_suites(TestHost& host, std::vector<std::shared_ptr<TestSuit
|
||||
auto suite = std::make_shared<WindowClipTests>(host, output_directory);
|
||||
test_suites.push_back(suite);
|
||||
}
|
||||
{
|
||||
auto suite = std::make_shared<ZMinMaxControlTests>(host, output_directory);
|
||||
test_suites.push_back(suite);
|
||||
}
|
||||
{
|
||||
auto suite = std::make_shared<ZeroStrideTests>(host, output_directory);
|
||||
test_suites.push_back(suite);
|
||||
|
15
src/shaders/passthrough.vsh
Normal file
15
src/shaders/passthrough.vsh
Normal file
@ -0,0 +1,15 @@
|
||||
; A vertex shader that just passes through all parameters with no manipulation.
|
||||
; Note that iWeight and iNormal are ignored as they'd generally be used in
|
||||
; per-vertex lighting.
|
||||
|
||||
mov oPos, iPos
|
||||
mov oDiffuse, iDiffuse
|
||||
mov oSpecular, iSpecular
|
||||
mov oFog, iFog
|
||||
mov oPts, iPts
|
||||
mov oBackDiffuse, iBackDiffuse
|
||||
mov oBackSpecular, iBackSpecular
|
||||
mov oTex0, iTex0
|
||||
mov oTex1, iTex1
|
||||
mov oTex2, iTex2
|
||||
mov oTex3, iTex3
|
@ -46,7 +46,10 @@ class ProjectionVertexShader : public VertexShaderProgram {
|
||||
// Projects the given point (on the CPU), placing the resulting screen coordinates into `result`.
|
||||
void ProjectPoint(vector_t &result, const vector_t &world_point) const;
|
||||
|
||||
//! Unprojects the given screen point, producing world coordinates that will project there.
|
||||
void UnprojectPoint(vector_t &result, const vector_t &screen_point) const;
|
||||
|
||||
//! Unprojects the given screen point, producing world coordinates that will project there with the given Z value.
|
||||
void UnprojectPoint(vector_t &result, const vector_t &screen_point, float world_z) const;
|
||||
|
||||
protected:
|
||||
|
@ -875,7 +875,7 @@ void TestHost::SaveRawTexture(const std::string &output_directory, const std::st
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void TestHost::SetupControl0(bool enable_stencil_write) const {
|
||||
void TestHost::SetupControl0(bool enable_stencil_write, bool w_buffered) const {
|
||||
// FIXME: Figure out what to do in cases where there are multiple stages with different conversion needs.
|
||||
// Is this supported by hardware?
|
||||
bool requires_colorspace_conversion = texture_stage_[0].RequiresColorspaceConversion();
|
||||
@ -883,6 +883,7 @@ void TestHost::SetupControl0(bool enable_stencil_write) const {
|
||||
uint32_t control0 = enable_stencil_write ? NV097_SET_CONTROL0_STENCIL_WRITE_ENABLE : 0;
|
||||
control0 |= MASK(NV097_SET_CONTROL0_Z_FORMAT,
|
||||
depth_buffer_mode_float_ ? NV097_SET_CONTROL0_Z_FORMAT_FLOAT : NV097_SET_CONTROL0_Z_FORMAT_FIXED);
|
||||
control0 |= MASK(NV097_SET_CONTROL0_Z_PERSPECTIVE_ENABLE, w_buffered ? 1 : 0);
|
||||
|
||||
if (requires_colorspace_conversion) {
|
||||
control0 |= MASK(NV097_SET_CONTROL0_COLOR_SPACE_CONVERT, NV097_SET_CONTROL0_COLOR_SPACE_CONVERT_CRYCB_TO_RGB);
|
||||
@ -1105,6 +1106,11 @@ void TestHost::BuildD3DProjectionViewportMatrix(matrix4_t &result, float fov, fl
|
||||
MatrixMultMatrix(projection, viewport, result);
|
||||
}
|
||||
|
||||
void TestHost::BuildD3DOrthographicProjectionMatrix(XboxMath::matrix4_t &result, float left, float right, float top,
|
||||
float bottom, float z_near, float z_far) {
|
||||
CreateD3DOrthographicLH(result, left, right, top, bottom, z_near, z_far);
|
||||
}
|
||||
|
||||
void TestHost::BuildDefaultXDKProjectionMatrix(matrix4_t &matrix) const {
|
||||
BuildD3DProjectionViewportMatrix(matrix, M_PI * 0.25f, 1.0f, 200.0f);
|
||||
}
|
||||
@ -1192,6 +1198,7 @@ void TestHost::SetFixedFunctionProjectionMatrix(const matrix4_t projection_matri
|
||||
|
||||
GetCompositeMatrix(fixed_function_composite_matrix_, fixed_function_model_view_matrix_,
|
||||
fixed_function_projection_matrix_);
|
||||
|
||||
auto p = pb_begin();
|
||||
p = pb_push_transposed_matrix(p, NV097_SET_COMPOSITE_MATRIX, fixed_function_composite_matrix_[0]);
|
||||
pb_end(p);
|
||||
@ -1200,6 +1207,11 @@ void TestHost::SetFixedFunctionProjectionMatrix(const matrix4_t projection_matri
|
||||
MatrixInvert(fixed_function_composite_matrix_, fixed_function_inverse_composite_matrix_);
|
||||
|
||||
fixed_function_matrix_mode_ = MATRIX_MODE_USER;
|
||||
|
||||
// https://developer.download.nvidia.com/assets/gamedev/docs/W_buffering2.pdf
|
||||
auto &proj = fixed_function_projection_matrix_;
|
||||
w_near_ = proj[3][3] - (proj[3][2] / proj[2][2] * proj[2][3]);
|
||||
w_far_ = (proj[3][3] - proj[3][2]) / (proj[2][2] - proj[2][3]) * proj[2][3] + proj[3][3];
|
||||
}
|
||||
|
||||
void TestHost::SetTextureStageEnabled(uint32_t stage, bool enabled) {
|
||||
|
@ -342,6 +342,10 @@ class TestHost {
|
||||
// Gets a D3D-style matrix suitable for a projection + viewport transform.
|
||||
void BuildD3DProjectionViewportMatrix(matrix4_t &result, float fov, float z_near, float z_far) const;
|
||||
|
||||
//! Builds an orthographic projection matrix.
|
||||
static void BuildD3DOrthographicProjectionMatrix(matrix4_t &result, float left, float right, float top, float bottom,
|
||||
float z_near, float z_far);
|
||||
|
||||
// Gets a reasonable default model view matrix (camera at z=-7.0f looking at the origin)
|
||||
static void BuildDefaultXDKModelViewMatrix(matrix4_t &matrix);
|
||||
// Gets a reasonable default projection matrix (fov = PI/4, near = 1, far = 200)
|
||||
@ -372,6 +376,9 @@ class TestHost {
|
||||
inline const matrix4_t &GetFixedFunctionModelViewMatrix() const { return fixed_function_model_view_matrix_; }
|
||||
inline const matrix4_t &GetFixedFunctionProjectionMatrix() const { return fixed_function_projection_matrix_; }
|
||||
|
||||
float GetWNear() const { return w_near_; }
|
||||
float GetWFar() const { return w_far_; }
|
||||
|
||||
// Start the process of rendering an inline-defined primitive (specified via SetXXXX methods below).
|
||||
// Note that End() must be called to trigger rendering, and that SetVertex() triggers the creation of a vertex.
|
||||
void Begin(DrawPrimitive primitive) const;
|
||||
@ -526,7 +533,8 @@ class TestHost {
|
||||
}
|
||||
}
|
||||
|
||||
void SetupControl0(bool enable_stencil_write = true) const;
|
||||
//! Set up the control0 register, controlling stencil writing and depth buffer mode.
|
||||
void SetupControl0(bool enable_stencil_write = true, bool w_buffered = false) const;
|
||||
|
||||
// Commit any changes to texture stages (called automatically in PrepareDraw but may be useful to call more frequently
|
||||
// in scenes with multiple draws per clear)
|
||||
@ -604,6 +612,9 @@ class TestHost {
|
||||
matrix4_t fixed_function_composite_matrix_{};
|
||||
matrix4_t fixed_function_inverse_composite_matrix_{};
|
||||
|
||||
float w_near_{0.f};
|
||||
float w_far_{0.f};
|
||||
|
||||
bool save_results_{true};
|
||||
|
||||
uint32_t vertex_attribute_stride_override_[16]{
|
||||
|
@ -120,7 +120,7 @@ void ColorKeyTests::TearDownTest() {
|
||||
pb_end(p);
|
||||
}
|
||||
|
||||
static void add_vertex(TestHost& host, float x, float y, float u, float v) {
|
||||
static void AddVertex(TestHost& host, float x, float y, float u, float v) {
|
||||
host.SetDiffuse(0.4f, 0.1f, 0.8f);
|
||||
host.SetTexCoord0(u, v);
|
||||
host.SetTexCoord1(u, v);
|
||||
@ -138,10 +138,10 @@ static void DrawQuads(TestHost& host, float x = 0.f, float y = 0.f) {
|
||||
|
||||
auto size = 0.75f;
|
||||
|
||||
add_vertex(host, -size + x, size + y, 0.f * kTextureSize, 0.f * kTextureSize);
|
||||
add_vertex(host, size + x, size + y, 1.f * kTextureSize, 0.f * kTextureSize);
|
||||
add_vertex(host, size + x, -size + y, 1.f * kTextureSize, 1.f * kTextureSize);
|
||||
add_vertex(host, -size + x, -size + y, 0.f * kTextureSize, 1.f * kTextureSize);
|
||||
AddVertex(host, -size + x, size + y, 0.f * kTextureSize, 0.f * kTextureSize);
|
||||
AddVertex(host, size + x, size + y, 1.f * kTextureSize, 0.f * kTextureSize);
|
||||
AddVertex(host, size + x, -size + y, 1.f * kTextureSize, 1.f * kTextureSize);
|
||||
AddVertex(host, -size + x, -size + y, 0.f * kTextureSize, 1.f * kTextureSize);
|
||||
|
||||
host.End();
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include "vertex_buffer.h"
|
||||
|
||||
static constexpr uint32_t kF16MaxFixedRepresentation = 0x0000FFFF;
|
||||
static constexpr uint32_t kF24MaxFixedRepresentation = 0x00FEFFFF;
|
||||
// static constexpr uint32_t kF24MaxFixedRepresentation = 0x00FEFFFF;
|
||||
|
||||
// Keep in sync with the value used to set up the default XDK composite matrix.
|
||||
static constexpr float kCameraZ = -7.0f;
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include "vertex_buffer.h"
|
||||
|
||||
static constexpr uint32_t kF16MaxFixedRepresentation = 0x0000FFFF;
|
||||
static constexpr uint32_t kF24MaxFixedRepresentation = 0x00FEFFFF;
|
||||
// static constexpr uint32_t kF24MaxFixedRepresentation = 0x00FEFFFF;
|
||||
|
||||
constexpr DepthFormatTests::DepthFormat kDepthFormats[] = {
|
||||
{NV097_SET_SURFACE_FORMAT_ZETA_Z16, 0x0000FFFF, false},
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include "texture_generator.h"
|
||||
|
||||
static constexpr const char kStopBehavior[] = "Stop";
|
||||
static constexpr const char kAlternateStop[] = "Stop Alt";
|
||||
// static constexpr const char kAlternateStop[] = "Stop Alt";
|
||||
|
||||
static constexpr const char kSizeInMaxUnity[] = "Size In Max - dI/dO = 1";
|
||||
static constexpr const char kSizeInMaxLarge[] = "Size In Max - dI/dO > 1";
|
||||
|
@ -92,6 +92,10 @@ void TestSuite::Initialize() {
|
||||
host_.GetFramebufferHeight());
|
||||
|
||||
auto p = pb_begin();
|
||||
p = pb_push4f(p, NV097_SET_EYE_POSITION, 0.0f, 0.0f, 0.0f, 1.0f);
|
||||
p = pb_push1(p, NV097_SET_ZMIN_MAX_CONTROL,
|
||||
NV097_SET_ZMIN_MAX_CONTROL_CULL_NEAR_FAR_EN_TRUE | NV097_SET_ZMIN_MAX_CONTROL_ZCLAMP_EN_CULL |
|
||||
NV097_SET_ZMIN_MAX_CONTROL_CULL_IGNORE_W_FALSE);
|
||||
p = pb_push1(p, NV097_SET_SURFACE_PITCH,
|
||||
SET_MASK(NV097_SET_SURFACE_PITCH_COLOR, kFramebufferPitch) |
|
||||
SET_MASK(NV097_SET_SURFACE_PITCH_ZETA, kFramebufferPitch));
|
||||
|
@ -137,7 +137,10 @@ TexgenMatrixTests::TexgenMatrixTests(TestHost &host, std::string output_dir)
|
||||
std::string test_name = name + "_Arbitrary";
|
||||
tests_[test_name] = [this, test_name, mode]() {
|
||||
matrix4_t matrix = {
|
||||
0.7089392, 0.0, 0.515, 0.0, 0.0, 1.2603364, 0.49, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0,
|
||||
{0.7089392, 0.0, 0.515, 0.0},
|
||||
{0.0, 1.2603364, 0.49, 0.0},
|
||||
{0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 0.0, 1.0, 0.0},
|
||||
};
|
||||
Test(test_name, matrix, mode);
|
||||
};
|
||||
|
@ -726,7 +726,7 @@ void TextureBorderTests::TestCubemapBorderedSwizzled(const std::string &name, ui
|
||||
|
||||
auto draw = [this, &shader, width](float x, float y, float z, float r_x, float r_y, float r_z,
|
||||
bool include_border = false) {
|
||||
matrix4_t matrix = {0.0f};
|
||||
matrix4_t matrix;
|
||||
vector_t eye{0.0f, 0.0f, -7.0f, 1.0f};
|
||||
vector_t at{0.0f, 0.0f, 0.0f, 1.0f};
|
||||
vector_t up{0.0f, 1.0f, 0.0f, 1.0f};
|
||||
|
@ -153,7 +153,7 @@ void TextureCubemapTests::TestCubemap() {
|
||||
auto shader = std::static_pointer_cast<PerspectiveVertexShader>(host_.GetShaderProgram());
|
||||
|
||||
auto draw = [this, &shader](float x, float y, float z, float r_x, float r_y, float r_z) {
|
||||
matrix4_t matrix = {0.0f};
|
||||
matrix4_t matrix;
|
||||
vector_t eye{0.0f, 0.0f, -7.0f, 1.0f};
|
||||
vector_t at{0.0f, 0.0f, 0.0f, 1.0f};
|
||||
vector_t up{0.0f, 1.0f, 0.0f, 1.0f};
|
||||
@ -239,11 +239,11 @@ void TextureCubemapTests::TestDotSTRCubemap(const std::string &name, uint32_t do
|
||||
host_.PrepareDraw(0xFE131313);
|
||||
|
||||
auto draw = [this, &shader](float x, float y, float z, float r_x, float r_y, float r_z) {
|
||||
matrix4_t matrix = {0.0f};
|
||||
matrix4_t matrix;
|
||||
vector_t eye{0.0f, 0.0f, -7.0f, 1.0f};
|
||||
vector_t at{0.0f, 0.0f, 0.0f, 1.0f};
|
||||
vector_t up{0.0f, 1.0f, 0.0f, 1.0f};
|
||||
host_.BuildD3DModelViewMatrix(matrix, eye, at, up);
|
||||
TestHost::BuildD3DModelViewMatrix(matrix, eye, at, up);
|
||||
|
||||
auto &model_matrix = shader->GetModelMatrix();
|
||||
MatrixSetIdentity(model_matrix);
|
||||
|
@ -121,7 +121,10 @@ TextureMatrixTests::TextureMatrixTests(TestHost &host, std::string output_dir)
|
||||
constexpr char kTestName[] = "Arbitrary";
|
||||
tests_[kTestName] = [this, kTestName]() {
|
||||
matrix4_t matrix = {
|
||||
0.7089392, 0.0, 0.515, 0.0, 0.0, 1.2603364, 0.49, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0,
|
||||
{0.7089392, 0.0, 0.515, 0.0},
|
||||
{0.0, 1.2603364, 0.49, 0.0},
|
||||
{0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 0.0, 1.0, 0.0},
|
||||
};
|
||||
Test(kTestName, matrix);
|
||||
};
|
||||
|
360
src/tests/z_min_max_control_tests.cpp
Normal file
360
src/tests/z_min_max_control_tests.cpp
Normal file
@ -0,0 +1,360 @@
|
||||
#include "z_min_max_control_tests.h"
|
||||
|
||||
#include <pbkit/pbkit.h>
|
||||
|
||||
#include "debug_output.h"
|
||||
#include "pbkit_ext.h"
|
||||
#include "shaders/perspective_vertex_shader.h"
|
||||
#include "texture_generator.h"
|
||||
#include "vertex_buffer.h"
|
||||
#include "xbox_math_d3d.h"
|
||||
#include "xbox_math_matrix.h"
|
||||
|
||||
constexpr uint32_t kSmallSize = 16;
|
||||
constexpr uint32_t kSmallSpacing = 4;
|
||||
constexpr uint32_t kStep = kSmallSize + kSmallSpacing;
|
||||
|
||||
static constexpr const char kTestName[] = "Ctrl";
|
||||
static constexpr const char kTestFixedName[] = "CtrlFixed";
|
||||
|
||||
static constexpr uint32_t kBackgroundColor = 0xFF222228;
|
||||
static constexpr float kZNear = 10.f;
|
||||
static constexpr float kZFar = 100.f;
|
||||
static constexpr float kWNear = 10.f;
|
||||
static constexpr float kWFar = 100.f;
|
||||
|
||||
static std::string MakeTestName(const char* prefix, uint32_t mode, bool w_buffered);
|
||||
|
||||
ZMinMaxControlTests::ZMinMaxControlTests(TestHost& host, std::string output_dir)
|
||||
: TestSuite(host, std::move(output_dir), "ZMinMaxControl") {
|
||||
for (auto w_buffered : {false, true}) {
|
||||
for (auto cull :
|
||||
{NV097_SET_ZMIN_MAX_CONTROL_CULL_NEAR_FAR_EN_FALSE, NV097_SET_ZMIN_MAX_CONTROL_CULL_NEAR_FAR_EN_TRUE}) {
|
||||
for (auto z_clamp : {NV097_SET_ZMIN_MAX_CONTROL_ZCLAMP_EN_CULL, NV097_SET_ZMIN_MAX_CONTROL_ZCLAMP_EN_CLAMP}) {
|
||||
for (auto ignore_w :
|
||||
{NV097_SET_ZMIN_MAX_CONTROL_CULL_IGNORE_W_FALSE, NV097_SET_ZMIN_MAX_CONTROL_CULL_IGNORE_W_TRUE}) {
|
||||
uint32_t mode = cull | z_clamp | ignore_w;
|
||||
{
|
||||
std::string name = MakeTestName(kTestName, mode, w_buffered);
|
||||
tests_[name] = [this, name, mode, w_buffered]() { this->Test(name, mode, w_buffered); };
|
||||
}
|
||||
{
|
||||
std::string name = MakeTestName(kTestFixedName, mode, w_buffered);
|
||||
tests_[name] = [this, name, mode, w_buffered]() { this->TestFixed(name, mode, w_buffered); };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const auto fb_width = host.GetFramebufferWidthF();
|
||||
const auto fb_height = host.GetFramebufferHeightF();
|
||||
|
||||
kLeft = floorf(fb_width / 5.0f);
|
||||
kRight = fb_width - kLeft;
|
||||
kTop = floorf(fb_height / 10.0f);
|
||||
kBottom = fb_height - kTop;
|
||||
kRegionWidth = (kRight - kLeft) * 0.33f;
|
||||
kRegionHeight = (kBottom - kTop) * 0.5f;
|
||||
|
||||
quads_per_row_ = static_cast<uint32_t>(kRegionWidth - kSmallSize) / kStep;
|
||||
quads_per_col_ = static_cast<uint32_t>(kRegionHeight - kSmallSize) / kStep;
|
||||
|
||||
col_size_ = static_cast<float>(kSmallSize) + static_cast<float>(quads_per_col_) * kStep;
|
||||
num_quads_ = quads_per_row_ * quads_per_col_;
|
||||
}
|
||||
|
||||
void ZMinMaxControlTests::Initialize() { TestSuite::Initialize(); }
|
||||
|
||||
void ZMinMaxControlTests::TearDownTest() {
|
||||
TestSuite::TearDownTest();
|
||||
host_.SetupControl0();
|
||||
host_.SetSurfaceFormat(TestHost::SCF_A8R8G8B8, TestHost::SZF_Z16, host_.GetFramebufferWidth(),
|
||||
host_.GetFramebufferHeight());
|
||||
auto p = pb_begin();
|
||||
p = pb_push1(p, NV097_SET_ZMIN_MAX_CONTROL,
|
||||
NV097_SET_ZMIN_MAX_CONTROL_CULL_NEAR_FAR_EN_TRUE | NV097_SET_ZMIN_MAX_CONTROL_ZCLAMP_EN_CULL |
|
||||
NV097_SET_ZMIN_MAX_CONTROL_CULL_IGNORE_W_FALSE);
|
||||
pb_end(p);
|
||||
}
|
||||
|
||||
static void AddVertex(TestHost& host, const vector_t& position, float r, float g, float b) {
|
||||
host.SetDiffuse(r, g, b);
|
||||
host.SetVertex(position);
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
static const uint32_t kPassthroughVsh[] = {
|
||||
#include "passthrough.vshinc"
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
void ZMinMaxControlTests::DrawBlock(float x_offset, float y_offset, ZMinMaxDrawMode zw_mode, bool projected) const {
|
||||
const float z_min = 0.f;
|
||||
const float z_max = kZFar * 1.5f;
|
||||
const float w_min = 0.f;
|
||||
const float w_max = kWFar * 1.5f;
|
||||
|
||||
float z_inc = (z_max - z_min) / (static_cast<float>(num_quads_) + 1.f);
|
||||
float w_inc = (w_max - w_min) / (static_cast<float>(num_quads_) + 1.f);
|
||||
|
||||
float z_left = z_min;
|
||||
float w_left = w_min;
|
||||
float right_offset_z = z_inc * 0.75f;
|
||||
float right_offset_w = w_inc * 0.75f;
|
||||
float y = y_offset;
|
||||
|
||||
for (int y_idx = 0; y_idx < quads_per_col_; ++y_idx) {
|
||||
float x = x_offset;
|
||||
for (int x_idx = 0; x_idx < quads_per_row_; ++x_idx) {
|
||||
float z_right = z_left + right_offset_z;
|
||||
float w_right = w_left + right_offset_w;
|
||||
|
||||
Color left;
|
||||
Color right;
|
||||
|
||||
const float left_z_color = 0.25f + z_left / z_max * 0.75f;
|
||||
const float right_z_color = 0.25f + z_right / z_max * 0.75f;
|
||||
const float left_w_color = 0.25f + w_left / w_max * 0.75f;
|
||||
const float right_w_color = 0.25f + w_right / w_max * 0.75f;
|
||||
|
||||
switch (zw_mode) {
|
||||
case M_Z_INC_W_ONE:
|
||||
left.SetGrey(left_z_color);
|
||||
right.SetGrey(right_z_color);
|
||||
w_left = 1.f;
|
||||
w_right = 1.f;
|
||||
break;
|
||||
|
||||
case M_Z_INC_W_INC: {
|
||||
left.SetRGB(left_z_color, 0.25f, left_w_color);
|
||||
right.SetRGB(right_z_color, 0.25f, right_w_color);
|
||||
} break;
|
||||
|
||||
case M_Z_NF_W_INC:
|
||||
left.SetRGB(0.33f, 0.25f, left_w_color);
|
||||
right.SetRGB(0.33f, 0.25f, right_w_color);
|
||||
z_left = kZNear * 0.8f;
|
||||
z_right = kZFar * 1.2f;
|
||||
break;
|
||||
|
||||
case M_Z_NF_W_NF:
|
||||
left.SetRGB(0.33f, 0.75f, 0.25f);
|
||||
right.SetRGB(0.33f, 0.75f, 0.8f);
|
||||
z_left = kZNear * 0.8f;
|
||||
z_right = kZFar * 1.2f;
|
||||
w_left = kWNear * 0.8f;
|
||||
w_right = kWFar * 1.2f;
|
||||
break;
|
||||
|
||||
case M_Z_INC_W_TEN:
|
||||
left.SetRGB(left_z_color, left_z_color, 0.25f);
|
||||
right.SetRGB(right_z_color, right_z_color, 0.8f);
|
||||
w_left = 10.f;
|
||||
w_right = 10.f;
|
||||
break;
|
||||
|
||||
case M_Z_INC_W_FRAC:
|
||||
left.SetRGB(0.75f, left_z_color, left_z_color);
|
||||
right.SetRGB(right_z_color, right_z_color, 0.8f);
|
||||
w_left = 0.01f;
|
||||
w_right = 0.0001f;
|
||||
break;
|
||||
|
||||
case M_Z_INC_W_INV_Z:
|
||||
left.SetRGB(0.5f, left_z_color, 0.5f);
|
||||
right.SetRGB(0.5f, right_z_color, 0.5f);
|
||||
w_left = 1.f / z_left;
|
||||
w_right = 1.f / z_right;
|
||||
}
|
||||
|
||||
if (!projected) {
|
||||
AddVertex(host_, {x, y, z_left, w_left}, left.r, left.g, left.b);
|
||||
AddVertex(host_, {x + kSmallSize, y, z_right, w_right}, right.r, right.g, right.b);
|
||||
AddVertex(host_, {x + kSmallSize, y + kSmallSize, z_right, w_right}, right.r, right.g, right.b);
|
||||
AddVertex(host_, {x, y + kSmallSize, z_left, w_left}, left.r, left.g, left.b);
|
||||
} else {
|
||||
auto w_adjust = [](vector_t& pt, float w) {
|
||||
pt[0] *= w;
|
||||
pt[1] *= w;
|
||||
pt[2] *= w;
|
||||
pt[3] = w;
|
||||
};
|
||||
|
||||
vector_t world_pt;
|
||||
host_.UnprojectPoint(world_pt, {x, y, z_left, 1.f});
|
||||
w_adjust(world_pt, w_left);
|
||||
AddVertex(host_, world_pt, left.r, left.g, left.b);
|
||||
|
||||
host_.UnprojectPoint(world_pt, {x + kSmallSize, y, z_right, 1.f});
|
||||
// host_.UnprojectPoint(world_pt, {x + kSmallSize, y, 0.f, 1.f}, z_right);
|
||||
w_adjust(world_pt, w_right);
|
||||
AddVertex(host_, world_pt, right.r, right.g, right.b);
|
||||
|
||||
host_.UnprojectPoint(world_pt, {x + kSmallSize, y + kSmallSize, z_right, 1.f});
|
||||
// host_.UnprojectPoint(world_pt, {x + kSmallSize, y + kSmallSize, 0.f, 1.f}, z_right);
|
||||
w_adjust(world_pt, w_right);
|
||||
AddVertex(host_, world_pt, right.r, right.g, right.b);
|
||||
|
||||
host_.UnprojectPoint(world_pt, {x, y + kSmallSize, z_left, 1.f});
|
||||
// host_.UnprojectPoint(world_pt, {x, y + kSmallSize, 0.f, 1.f}, z_left);
|
||||
w_adjust(world_pt, w_left);
|
||||
AddVertex(host_, world_pt, left.r, left.g, left.b);
|
||||
}
|
||||
|
||||
z_left += z_inc;
|
||||
w_left += w_inc;
|
||||
x += kStep;
|
||||
}
|
||||
|
||||
y += kStep;
|
||||
}
|
||||
}
|
||||
|
||||
void ZMinMaxControlTests::Test(const std::string& name, uint32_t mode, bool w_buffered) {
|
||||
auto shader = std::make_shared<VertexShaderProgram>();
|
||||
shader->SetShaderOverride(kPassthroughVsh, sizeof(kPassthroughVsh));
|
||||
host_.SetVertexShaderProgram(shader);
|
||||
|
||||
host_.PrepareDraw(kBackgroundColor);
|
||||
|
||||
if (w_buffered) {
|
||||
host_.SetDepthClip(kWNear, kWFar);
|
||||
} else {
|
||||
host_.SetDepthClip(kZNear, kZFar);
|
||||
}
|
||||
|
||||
auto p = pb_begin();
|
||||
p = pb_push1(p, NV097_SET_ZMIN_MAX_CONTROL, mode);
|
||||
pb_end(p);
|
||||
|
||||
const float zscale = host_.GetMaxDepthBufferValue();
|
||||
host_.SetupControl0(false, w_buffered);
|
||||
TestHost::SetViewportScale(320.f, -240.f, zscale, w_buffered ? 1.f : 0.f);
|
||||
|
||||
host_.Begin(TestHost::PRIMITIVE_QUADS);
|
||||
|
||||
float x_offset = 90.f;
|
||||
float y_offset = kTop + kSmallSpacing + (kRegionHeight - col_size_) * 0.5f;
|
||||
|
||||
DrawBlock(x_offset, y_offset, M_Z_INC_W_ONE);
|
||||
DrawBlock(x_offset, y_offset + kRegionHeight, M_Z_NF_W_INC);
|
||||
|
||||
x_offset += kRegionWidth + 90.f;
|
||||
|
||||
DrawBlock(x_offset, y_offset, M_Z_INC_W_FRAC);
|
||||
DrawBlock(x_offset, y_offset + kRegionHeight, M_Z_NF_W_NF);
|
||||
|
||||
x_offset += kRegionWidth + 90.f;
|
||||
|
||||
DrawBlock(x_offset, y_offset, M_Z_INC_W_INC);
|
||||
DrawBlock(x_offset, y_offset + kRegionHeight, M_Z_INC_W_TEN);
|
||||
|
||||
host_.End();
|
||||
|
||||
pb_print("%s\n", name.c_str());
|
||||
pb_printat(2, 1, (char*)"Z=Inc");
|
||||
pb_printat(2, 21, (char*)"Z=Inc");
|
||||
pb_printat(2, 44, (char*)"Z=Inc");
|
||||
pb_printat(3, 1, (char*)"W=1");
|
||||
pb_printat(3, 21, (char*)"W=Frac");
|
||||
pb_printat(3, 44, (char*)"W=Inc");
|
||||
|
||||
pb_printat(11, 1, (char*)"Z=N->F");
|
||||
pb_printat(11, 21, (char*)"Z=N->F");
|
||||
pb_printat(11, 44, (char*)"Z=Inc");
|
||||
pb_printat(12, 1, (char*)"W=Inc");
|
||||
pb_printat(12, 21, (char*)"W=N->F");
|
||||
pb_printat(12, 44, (char*)"W=10");
|
||||
|
||||
pb_draw_text_screen();
|
||||
host_.FinishDraw(allow_saving_, output_dir_, name);
|
||||
}
|
||||
|
||||
void ZMinMaxControlTests::TestFixed(const std::string& name, uint32_t mode, bool w_buffered) {
|
||||
host_.SetVertexShaderProgram(nullptr);
|
||||
host_.SetXDKDefaultViewportAndFixedFunctionMatrices();
|
||||
|
||||
host_.PrepareDraw(kBackgroundColor);
|
||||
|
||||
TestHost::SetViewportScale(0.f, 0.f, 0.f, 0.f);
|
||||
|
||||
matrix4_t matrix;
|
||||
XboxMath::MatrixSetIdentity(matrix);
|
||||
XboxMath::MatrixTranslate(matrix, {0.f, 0.f, -3.f, 1.f});
|
||||
host_.SetFixedFunctionModelViewMatrix(matrix);
|
||||
|
||||
const auto near_plane = w_buffered ? kWNear : kZNear;
|
||||
const auto far_plane = w_buffered ? kWFar : kZFar;
|
||||
TestHost::BuildD3DOrthographicProjectionMatrix(matrix, -320.f, 320.f, 240.f, -240.f, near_plane, far_plane);
|
||||
matrix4_t viewport;
|
||||
const auto fb_width = host_.GetFramebufferWidthF();
|
||||
const auto fb_height = host_.GetFramebufferHeightF();
|
||||
XboxMath::CreateD3DStandardViewport16Bit(viewport, fb_width, fb_height);
|
||||
matrix4_t proj_viewport;
|
||||
MatrixMultMatrix(matrix, viewport, proj_viewport);
|
||||
host_.SetFixedFunctionProjectionMatrix(proj_viewport);
|
||||
|
||||
host_.SetupControl0(false, w_buffered);
|
||||
if (w_buffered) {
|
||||
host_.SetDepthClip(kWNear, kWFar);
|
||||
} else {
|
||||
host_.SetDepthClip(kZNear, kZFar);
|
||||
}
|
||||
|
||||
auto p = pb_begin();
|
||||
p = pb_push1(p, NV097_SET_ZMIN_MAX_CONTROL, mode);
|
||||
pb_end(p);
|
||||
|
||||
const float zscale = host_.GetMaxDepthBufferValue();
|
||||
host_.SetupControl0(false, w_buffered);
|
||||
TestHost::SetViewportScale(320.f, -240.f, zscale, w_buffered ? 1.f : 0.f);
|
||||
|
||||
host_.Begin(TestHost::PRIMITIVE_QUADS);
|
||||
|
||||
float x_offset = 90.f;
|
||||
float y_offset = kTop + kSmallSpacing + (kRegionHeight - col_size_) * 0.5f;
|
||||
|
||||
DrawBlock(x_offset, y_offset, M_Z_INC_W_ONE, true);
|
||||
DrawBlock(x_offset, y_offset + kRegionHeight, M_Z_NF_W_INC, true);
|
||||
|
||||
x_offset += kRegionWidth + 90.f;
|
||||
|
||||
DrawBlock(x_offset, y_offset, M_Z_INC_W_FRAC, true);
|
||||
DrawBlock(x_offset, y_offset + kRegionHeight, M_Z_NF_W_NF, true);
|
||||
|
||||
x_offset += kRegionWidth + 90.f;
|
||||
|
||||
DrawBlock(x_offset, y_offset, M_Z_INC_W_INC, true);
|
||||
DrawBlock(x_offset, y_offset + kRegionHeight, M_Z_INC_W_TEN, true);
|
||||
|
||||
host_.End();
|
||||
|
||||
pb_print("%s\n", name.c_str());
|
||||
pb_printat(2, 1, (char*)"Z=Inc");
|
||||
pb_printat(2, 21, (char*)"Z=Inc");
|
||||
pb_printat(2, 44, (char*)"Z=Inc");
|
||||
pb_printat(3, 1, (char*)"W=1");
|
||||
pb_printat(3, 21, (char*)"W=Frac");
|
||||
pb_printat(3, 44, (char*)"W=Inc");
|
||||
|
||||
pb_printat(11, 1, (char*)"Z=N->F");
|
||||
pb_printat(11, 21, (char*)"Z=N->F");
|
||||
pb_printat(11, 44, (char*)"Z=Inc");
|
||||
pb_printat(12, 1, (char*)"W=Inc");
|
||||
pb_printat(12, 21, (char*)"W=N->F");
|
||||
pb_printat(12, 44, (char*)"W=10");
|
||||
|
||||
pb_draw_text_screen();
|
||||
host_.FinishDraw(allow_saving_, output_dir_, name);
|
||||
}
|
||||
|
||||
static std::string MakeTestName(const char* prefix, uint32_t mode, bool w_buffered) {
|
||||
std::string ret = prefix;
|
||||
ret += w_buffered ? "_WBuf" : "";
|
||||
ret += (mode & NV097_SET_ZMIN_MAX_CONTROL_CULL_NEAR_FAR_EN_TRUE) ? "_NEARFAR" : "";
|
||||
ret += (mode & NV097_SET_ZMIN_MAX_CONTROL_ZCLAMP_EN_CLAMP) ? "_ZCLAMP" : "_ZCULL";
|
||||
ret += (mode & NV097_SET_ZMIN_MAX_CONTROL_CULL_IGNORE_W_TRUE) ? "_IgnW" : "";
|
||||
|
||||
return ret;
|
||||
}
|
52
src/tests/z_min_max_control_tests.h
Normal file
52
src/tests/z_min_max_control_tests.h
Normal file
@ -0,0 +1,52 @@
|
||||
#ifndef NXDK_PGRAPH_TESTS_Z_MIN_MAX_CONTROL_TESTS_H
|
||||
#define NXDK_PGRAPH_TESTS_Z_MIN_MAX_CONTROL_TESTS_H
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "test_host.h"
|
||||
#include "test_suite.h"
|
||||
|
||||
class TestHost;
|
||||
class VertexBuffer;
|
||||
|
||||
// Tests 0x1D78 NV097_SET_ZMIN_MAX_CONTROL functions.
|
||||
class ZMinMaxControlTests : public TestSuite {
|
||||
public:
|
||||
typedef enum ZMinMaxDrawMode {
|
||||
M_Z_INC_W_ONE,
|
||||
M_Z_INC_W_INC,
|
||||
M_Z_NF_W_INC,
|
||||
M_Z_NF_W_NF,
|
||||
M_Z_INC_W_TEN,
|
||||
M_Z_INC_W_FRAC,
|
||||
M_Z_INC_W_INV_Z,
|
||||
} ZMinMaxDrawMode;
|
||||
|
||||
public:
|
||||
ZMinMaxControlTests(TestHost& host, std::string output_dir);
|
||||
|
||||
void Initialize() override;
|
||||
void TearDownTest() override;
|
||||
|
||||
private:
|
||||
void Test(const std::string& name, uint32_t mode, bool w_buffered);
|
||||
void TestFixed(const std::string& name, uint32_t mode, bool w_buffered);
|
||||
|
||||
void DrawBlock(float x_offset, float y_offset, ZMinMaxDrawMode zw_mode, bool projected = false) const;
|
||||
|
||||
private:
|
||||
float kLeft{0.f};
|
||||
float kRight{0.f};
|
||||
float kTop{0.f};
|
||||
float kBottom{0.f};
|
||||
float kRegionWidth{0.f};
|
||||
float kRegionHeight{0.f};
|
||||
|
||||
uint32_t quads_per_row_{0};
|
||||
uint32_t quads_per_col_{0};
|
||||
float col_size_{0.f};
|
||||
uint32_t num_quads_{0};
|
||||
};
|
||||
|
||||
#endif // NXDK_PGRAPH_TESTS_Z_MIN_MAX_CONTROL_TESTS_H
|
2
third_party/xbox_math3d
vendored
2
third_party/xbox_math3d
vendored
@ -1 +1 @@
|
||||
Subproject commit bff2424b219959ecaf4c79b344132029c6fab3a6
|
||||
Subproject commit a898f1f93f66d6fd2c7ae4eef64a5643809dc7ad
|
Loading…
x
Reference in New Issue
Block a user