mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-25 11:19:03 +01:00
Merge pull request #15069 from unknownbrackets/swtransform-project
Process projection inside software transform
This commit is contained in:
16 files changed
+169
-86
No files matched your search
@@ -134,6 +134,7 @@ void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipView
|
||||
flippedMatrix = flippedMatrix * g_display_rot_matrix;
|
||||
}
|
||||
CopyMatrix4x4(ub->proj, flippedMatrix.getReadPtr());
|
||||
ub->rotation = (float)g_display_rotation;
|
||||
}
|
||||
|
||||
if (dirtyUniforms & DIRTY_PROJTHROUGHMATRIX) {
|
||||
|
||||
@@ -28,7 +28,8 @@ struct UB_VS_FS_Base {
|
||||
float tex[12];
|
||||
float uvScaleOffset[4];
|
||||
float depthRange[4];
|
||||
float fogCoef[2]; float stencil; float pad0;
|
||||
// Rotation is used only for software transform.
|
||||
float fogCoef[2]; float stencil; float rotation;
|
||||
float matAmbient[4];
|
||||
float cullRangeMin[4];
|
||||
float cullRangeMax[4];
|
||||
@@ -55,6 +56,7 @@ R"( mat4 u_proj;
|
||||
vec4 u_depthRange;
|
||||
vec2 u_fogcoef;
|
||||
float u_stencilReplaceValue;
|
||||
float u_rotation;
|
||||
vec4 u_matambientalpha;
|
||||
vec4 u_cullRangeMin;
|
||||
vec4 u_cullRangeMax;
|
||||
|
||||
@@ -64,16 +64,14 @@ static void SwapUVs(TransformedVertex &a, TransformedVertex &b) {
|
||||
|
||||
// Note: 0 is BR and 2 is TL.
|
||||
|
||||
static void RotateUV(TransformedVertex v[4], Vec4f tl, Vec4f br, bool flippedY) {
|
||||
static void RotateUV(TransformedVertex v[4], bool flippedY) {
|
||||
// We use the transformed tl/br coordinates to figure out whether they're flipped or not.
|
||||
float ySign = flippedY ? -1.0 : 1.0;
|
||||
|
||||
const float invtlw = 1.0f / tl.w;
|
||||
const float invbrw = 1.0f / br.w;
|
||||
const float x1 = tl.x * invtlw;
|
||||
const float x2 = br.x * invbrw;
|
||||
const float y1 = tl.y * invtlw * ySign;
|
||||
const float y2 = br.y * invbrw * ySign;
|
||||
const float x1 = v[2].x;
|
||||
const float x2 = v[0].x;
|
||||
const float y1 = v[2].y * ySign;
|
||||
const float y2 = v[0].y * ySign;
|
||||
|
||||
if ((x1 < x2 && y1 < y2) || (x1 > x2 && y1 > y2))
|
||||
SwapUVs(v[1], v[3]);
|
||||
@@ -151,6 +149,25 @@ static int ColorIndexOffset(int prim, GEShadeMode shadeMode, bool clearMode) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SoftwareTransform::SetProjMatrix(float mtx[14], bool invertedX, bool invertedY, const Lin::Vec3 &trans, const Lin::Vec3 &scale) {
|
||||
memcpy(&projMatrix_.m, mtx, 16 * sizeof(float));
|
||||
|
||||
if (invertedY) {
|
||||
projMatrix_.xy = -projMatrix_.xy;
|
||||
projMatrix_.yy = -projMatrix_.yy;
|
||||
projMatrix_.zy = -projMatrix_.zy;
|
||||
projMatrix_.wy = -projMatrix_.wy;
|
||||
}
|
||||
if (invertedX) {
|
||||
projMatrix_.xx = -projMatrix_.xx;
|
||||
projMatrix_.yx = -projMatrix_.yx;
|
||||
projMatrix_.zx = -projMatrix_.zx;
|
||||
projMatrix_.wx = -projMatrix_.wx;
|
||||
}
|
||||
|
||||
projMatrix_.translateAndScale(trans, scale);
|
||||
}
|
||||
|
||||
void SoftwareTransform::Decode(int prim, u32 vertType, const DecVtxFormat &decVtxFormat, int maxIndex, SoftwareTransformResult *result) {
|
||||
u8 *decoded = params_.decoded;
|
||||
TransformedVertex *transformed = params_.transformed;
|
||||
@@ -196,6 +213,7 @@ void SoftwareTransform::Decode(int prim, u32 vertType, const DecVtxFormat &decVt
|
||||
// TODO: Write to a flexible buffer, we don't always need all four components.
|
||||
TransformedVertex &vert = transformed[index];
|
||||
reader.ReadPos(vert.pos);
|
||||
vert.posw = 1.0f;
|
||||
|
||||
if (reader.hasColor0()) {
|
||||
if (provokeIndOffset != 0 && index + provokeIndOffset < maxIndex) {
|
||||
@@ -412,14 +430,13 @@ void SoftwareTransform::Decode(int prim, u32 vertType, const DecVtxFormat &decVt
|
||||
fogCoef = (v[2] + fog_end) * fog_slope;
|
||||
|
||||
// TODO: Write to a flexible buffer, we don't always need all four components.
|
||||
memcpy(&transformed[index].x, v, 3 * sizeof(float));
|
||||
Vec3ByMatrix44(transformed[index].pos, v, projMatrix_.m);
|
||||
transformed[index].fog = fogCoef;
|
||||
memcpy(&transformed[index].u, uv, 3 * sizeof(float));
|
||||
memcpy(&transformed[index].uv, uv, 3 * sizeof(float));
|
||||
transformed[index].color0_32 = c0.ToRGBA();
|
||||
transformed[index].color1_32 = c1.ToRGBA();
|
||||
|
||||
// The multiplication by the projection matrix is still performed in the vertex shader.
|
||||
// So is vertex depth rounding, to simulate the 16-bit depth buffer.
|
||||
// Vertex depth rounding is done in the shader, to simulate the 16-bit depth buffer.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -428,7 +445,6 @@ void SoftwareTransform::Decode(int prim, u32 vertType, const DecVtxFormat &decVt
|
||||
//
|
||||
// An alternative option is to simply ditch all the verts except the first and last to create a single
|
||||
// rectangle out of many. Quite a small optimization though.
|
||||
// Experiment: Disable on PowerVR (see issue #6290)
|
||||
// TODO: This bleeds outside the play area in non-buffered mode. Big deal? Probably not.
|
||||
// TODO: Allow creating a depth clear and a color draw.
|
||||
bool reallyAClear = false;
|
||||
@@ -555,37 +571,11 @@ void SoftwareTransform::BuildDrawingParams(int prim, int vertexCount, u32 vertTy
|
||||
FramebufferManagerCommon *fbman = params_.fbman;
|
||||
bool useBufferedRendering = fbman->UseBufferedRendering();
|
||||
|
||||
bool flippedY = g_Config.iGPUBackend == (int)GPUBackend::OPENGL && !useBufferedRendering;
|
||||
|
||||
if (prim != GE_PRIM_RECTANGLES) {
|
||||
// We can simply draw the unexpanded buffer.
|
||||
numTrans = vertexCount;
|
||||
result->drawIndexed = true;
|
||||
} else {
|
||||
// Pretty bad hackery where we re-do the transform (in RotateUV) to see if the vertices are flipped in screen space.
|
||||
// Since we've already got API-specific assumptions (Y direction, etc) baked into the projMatrix (which we arguably shouldn't),
|
||||
// this gets nasty and very hard to understand.
|
||||
|
||||
float flippedMatrix[16];
|
||||
if (!throughmode) {
|
||||
memcpy(&flippedMatrix, gstate.projMatrix, 16 * sizeof(float));
|
||||
|
||||
const bool invertedY = flippedY ? (gstate_c.vpHeight < 0) : (gstate_c.vpHeight > 0);
|
||||
if (invertedY) {
|
||||
flippedMatrix[1] = -flippedMatrix[1];
|
||||
flippedMatrix[5] = -flippedMatrix[5];
|
||||
flippedMatrix[9] = -flippedMatrix[9];
|
||||
flippedMatrix[13] = -flippedMatrix[13];
|
||||
}
|
||||
const bool invertedX = gstate_c.vpWidth < 0;
|
||||
if (invertedX) {
|
||||
flippedMatrix[0] = -flippedMatrix[0];
|
||||
flippedMatrix[4] = -flippedMatrix[4];
|
||||
flippedMatrix[8] = -flippedMatrix[8];
|
||||
flippedMatrix[12] = -flippedMatrix[12];
|
||||
}
|
||||
}
|
||||
|
||||
//rectangles always need 2 vertices, disregard the last one if there's an odd number
|
||||
vertexCount = vertexCount & ~1;
|
||||
numTrans = 0;
|
||||
@@ -626,21 +616,8 @@ void SoftwareTransform::BuildDrawingParams(int prim, int vertexCount, u32 vertTy
|
||||
if (throughmode) {
|
||||
RotateUVThrough(trans);
|
||||
} else {
|
||||
Vec4f tl;
|
||||
Vec3ByMatrix44(tl.AsArray(), transVtxTL.pos, flippedMatrix);
|
||||
Vec4f br;
|
||||
Vec3ByMatrix44(br.AsArray(), transVtxBR.pos, flippedMatrix);
|
||||
|
||||
// If both transformed verts are outside Z, cull this rectangle entirely.
|
||||
constexpr float outsideValue = 1.000030517578125f;
|
||||
bool tlOutside = fabsf(tl.z / tl.w) >= outsideValue;
|
||||
bool brOutside = fabsf(br.z / br.w) >= outsideValue;
|
||||
if (tlOutside && brOutside)
|
||||
continue;
|
||||
if (!gstate.isDepthClampEnabled() && (tlOutside || brOutside))
|
||||
continue;
|
||||
|
||||
RotateUV(trans, tl, br, flippedY);
|
||||
// TODO: Should apply culling here, based on projection depth range.
|
||||
RotateUV(trans, params_.flippedY);
|
||||
}
|
||||
|
||||
// Triangle: BR-TR-TL
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
#include "VertexDecoderCommon.h"
|
||||
#include "Common/Math/lin/matrix4x4.h"
|
||||
#include "GPU/Common/VertexDecoderCommon.h"
|
||||
|
||||
class FramebufferManagerCommon;
|
||||
class TextureCacheCommon;
|
||||
@@ -56,6 +56,7 @@ struct SoftwareTransformParams {
|
||||
bool allowClear;
|
||||
bool allowSeparateAlphaClear;
|
||||
bool provokeFlatFirst;
|
||||
bool flippedY;
|
||||
};
|
||||
|
||||
class SoftwareTransform {
|
||||
@@ -63,10 +64,12 @@ public:
|
||||
SoftwareTransform(SoftwareTransformParams ¶ms) : params_(params) {
|
||||
}
|
||||
|
||||
void SetProjMatrix(float mtx[14], bool invertedX, bool invertedY, const Lin::Vec3 &trans, const Lin::Vec3 &scale);
|
||||
void Decode(int prim, u32 vertexType, const DecVtxFormat &decVtxFormat, int maxIndex, SoftwareTransformResult *result);
|
||||
void DetectOffsetTexture(int maxIndex);
|
||||
void BuildDrawingParams(int prim, int vertexCount, u32 vertType, u16 *&inds, int &maxIndex, SoftwareTransformResult *result);
|
||||
|
||||
protected:
|
||||
const SoftwareTransformParams ¶ms_;
|
||||
Lin::Matrix4x4 projMatrix_;
|
||||
};
|
||||
@@ -236,11 +236,12 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag
|
||||
if (useHWTransform)
|
||||
WRITE(p, "layout (location = %d) in vec3 position;\n", (int)PspAttributeLocation::POSITION);
|
||||
else
|
||||
// we pass the fog coord in w
|
||||
WRITE(p, "layout (location = %d) in vec4 position;\n", (int)PspAttributeLocation::POSITION);
|
||||
|
||||
if (useHWTransform && hasNormal)
|
||||
WRITE(p, "layout (location = %d) in vec3 normal;\n", (int)PspAttributeLocation::NORMAL);
|
||||
if (!useHWTransform && enableFog)
|
||||
WRITE(p, "layout (location = %d) in float fog;\n", (int)PspAttributeLocation::NORMAL);
|
||||
|
||||
if (doTexture && hasTexcoord) {
|
||||
if (!useHWTransform && doTextureTransform && !isModeThrough) {
|
||||
@@ -278,9 +279,10 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag
|
||||
WRITE(p, "#pragma warning( disable : 3571 )\n");
|
||||
if (isModeThrough) {
|
||||
WRITE(p, "mat4 u_proj_through : register(c%i);\n", CONST_VS_PROJ_THROUGH);
|
||||
} else {
|
||||
} else if (useHWTransform) {
|
||||
WRITE(p, "mat4 u_proj : register(c%i);\n", CONST_VS_PROJ);
|
||||
// Add all the uniforms we'll need to transform properly.
|
||||
} else {
|
||||
WRITE(p, "float u_rotation : register(c%i);\n", CONST_VS_ROTATION);
|
||||
}
|
||||
|
||||
if (enableFog) {
|
||||
@@ -385,6 +387,9 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag
|
||||
if (lmode) {
|
||||
WRITE(p, " vec3 color1 : COLOR1;\n");
|
||||
}
|
||||
if (enableFog) {
|
||||
WRITE(p, " float fog : NORMAL;\n");
|
||||
}
|
||||
WRITE(p, "};\n");
|
||||
}
|
||||
|
||||
@@ -434,6 +439,10 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag
|
||||
WRITE(p, "%s mediump vec3 normal;\n", compat.attribute);
|
||||
*attrMask |= 1 << ATTR_NORMAL;
|
||||
}
|
||||
if (!useHWTransform && enableFog) {
|
||||
WRITE(p, "%s highp float fog;\n", compat.attribute);
|
||||
*attrMask |= 1 << ATTR_NORMAL;
|
||||
}
|
||||
|
||||
if (doTexture && hasTexcoord) {
|
||||
if (!useHWTransform && doTextureTransform && !isModeThrough) {
|
||||
@@ -456,10 +465,9 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag
|
||||
if (isModeThrough) {
|
||||
WRITE(p, "uniform mat4 u_proj_through;\n");
|
||||
*uniformMask |= DIRTY_PROJTHROUGHMATRIX;
|
||||
} else {
|
||||
} else if (useHWTransform) {
|
||||
WRITE(p, "uniform mat4 u_proj;\n");
|
||||
*uniformMask |= DIRTY_PROJMATRIX;
|
||||
// Add all the uniforms we'll need to transform properly.
|
||||
}
|
||||
|
||||
if (useHWTransform) {
|
||||
@@ -519,6 +527,8 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag
|
||||
WRITE(p, "uniform lowp vec3 u_matemissive;\n");
|
||||
*uniformMask |= DIRTY_MATSPECULAR | DIRTY_MATEMISSIVE;
|
||||
}
|
||||
} else {
|
||||
WRITE(p, "uniform lowp float u_rotation;\n");
|
||||
}
|
||||
|
||||
if (useHWTransform || !hasColor) {
|
||||
@@ -763,6 +773,9 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag
|
||||
} else {
|
||||
WRITE(p, " vec4 position = In.position;\n");
|
||||
}
|
||||
if (!useHWTransform && enableFog) {
|
||||
WRITE(p, " float fog = In.fog;\n");
|
||||
}
|
||||
if (enableBones) {
|
||||
WRITE(p, "%s", boneWeightAttrInitHLSL[numBoneWeights]);
|
||||
}
|
||||
@@ -787,16 +800,24 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag
|
||||
WRITE(p, " %sv_color1 = splat3(0.0);\n", compat.vsOutPrefix);
|
||||
}
|
||||
if (enableFog) {
|
||||
WRITE(p, " %sv_fogdepth = position.w;\n", compat.vsOutPrefix);
|
||||
WRITE(p, " %sv_fogdepth = fog;\n", compat.vsOutPrefix);
|
||||
}
|
||||
if (isModeThrough) {
|
||||
WRITE(p, " vec4 outPos = mul(u_proj_through, vec4(position.xyz, 1.0));\n");
|
||||
} else {
|
||||
// Apply rotation from the uniform.
|
||||
WRITE(p, " mat4 displayRotation = mat4(\n");
|
||||
WRITE(p, " u_rotation == 0.0 ? 1.0 : (u_rotation == 2.0 ? -1.0 : 0.0), u_rotation == 1.0 ? 1.0 : (u_rotation == 3.0 ? -1.0 : 0.0), 0.0, 0.0,\n");
|
||||
WRITE(p, " u_rotation == 3.0 ? 1.0 : (u_rotation == 1.0 ? -1.0 : 0.0), u_rotation == 0.0 ? 1.0 : (u_rotation == 2.0 ? -1.0 : 0.0), 0.0, 0.0,\n");
|
||||
WRITE(p, " 0.0, 0.0, 1.0, 0.0,\n");
|
||||
WRITE(p, " 0.0, 0.0, 0.0, 1.0\n");
|
||||
WRITE(p, " );\n");
|
||||
|
||||
// The viewport is used in this case, so need to compensate for that.
|
||||
if (gstate_c.Supports(GPU_ROUND_DEPTH_TO_16BIT)) {
|
||||
WRITE(p, " vec4 outPos = depthRoundZVP(mul(u_proj, vec4(position.xyz, 1.0)));\n");
|
||||
WRITE(p, " vec4 outPos = depthRoundZVP(mul(displayRotation, position));\n");
|
||||
} else {
|
||||
WRITE(p, " vec4 outPos = mul(u_proj, vec4(position.xyz, 1.0));\n");
|
||||
WRITE(p, " vec4 outPos = mul(displayRotation, position);\n");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -60,4 +60,5 @@ enum {
|
||||
CONST_VS_BONE8 = 77,
|
||||
CONST_VS_CULLRANGEMIN = 80,
|
||||
CONST_VS_CULLRANGEMAX = 81,
|
||||
CONST_VS_ROTATION = 82,
|
||||
};
|
||||
@@ -61,10 +61,11 @@ enum {
|
||||
};
|
||||
|
||||
static const D3D11_INPUT_ELEMENT_DESC TransformedVertexElements[] = {
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 28, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 1, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 32, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(TransformedVertex, pos), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, offsetof(TransformedVertex, uv), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, offsetof(TransformedVertex, color0), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 1, DXGI_FORMAT_R8G8B8A8_UNORM, 0, offsetof(TransformedVertex, color1), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "NORMAL", 0, DXGI_FORMAT_R32_FLOAT, 0, offsetof(TransformedVertex, fog), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
|
||||
DrawEngineD3D11::DrawEngineD3D11(Draw::DrawContext *draw, ID3D11Device *device, ID3D11DeviceContext *context)
|
||||
@@ -586,9 +587,24 @@ rotateVBO:
|
||||
params.allowClear = true;
|
||||
params.allowSeparateAlphaClear = false; // D3D11 doesn't support separate alpha clears
|
||||
params.provokeFlatFirst = true;
|
||||
params.flippedY = false;
|
||||
|
||||
// We need correct viewport values in gstate_c already.
|
||||
if (gstate_c.IsDirty(DIRTY_VIEWPORTSCISSOR_STATE)) {
|
||||
ViewportAndScissor vpAndScissor;
|
||||
ConvertViewportAndScissor(framebufferManager_->UseBufferedRendering(),
|
||||
framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(),
|
||||
framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(),
|
||||
vpAndScissor);
|
||||
}
|
||||
|
||||
int maxIndex = indexGen.MaxIndex();
|
||||
SoftwareTransform swTransform(params);
|
||||
|
||||
const Lin::Vec3 trans(gstate_c.vpXOffset, gstate_c.vpYOffset, gstate_c.vpZOffset * 0.5f + 0.5f);
|
||||
const Lin::Vec3 scale(gstate_c.vpWidthScale, -gstate_c.vpHeightScale, gstate_c.vpDepthScale * 0.5f);
|
||||
swTransform.SetProjMatrix(gstate.projMatrix, gstate_c.vpWidth < 0, gstate_c.vpHeight < 0, trans, scale);
|
||||
|
||||
swTransform.Decode(prim, dec_->VertexType(), dec_->GetDecVtxFmt(), maxIndex, &result);
|
||||
if (result.action == SW_NOT_READY) {
|
||||
swTransform.DetectOffsetTexture(maxIndex);
|
||||
|
||||
@@ -77,10 +77,11 @@ enum {
|
||||
enum { VAI_KILL_AGE = 120, VAI_UNRELIABLE_KILL_AGE = 240, VAI_UNRELIABLE_KILL_MAX = 4 };
|
||||
|
||||
static const D3DVERTEXELEMENT9 TransformedVertexElements[] = {
|
||||
{ 0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
|
||||
{ 0, 16, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
|
||||
{ 0, 28, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 },
|
||||
{ 0, 32, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1 },
|
||||
{ 0, offsetof(TransformedVertex, pos), D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
|
||||
{ 0, offsetof(TransformedVertex, uv), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
|
||||
{ 0, offsetof(TransformedVertex, color0), D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 },
|
||||
{ 0, offsetof(TransformedVertex, color1), D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1 },
|
||||
{ 0, offsetof(TransformedVertex, fog), D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 },
|
||||
D3DDECL_END()
|
||||
};
|
||||
|
||||
@@ -555,9 +556,30 @@ rotateVBO:
|
||||
params.allowClear = true;
|
||||
params.allowSeparateAlphaClear = false;
|
||||
params.provokeFlatFirst = true;
|
||||
params.flippedY = false;
|
||||
|
||||
// We need correct viewport values in gstate_c already.
|
||||
if (gstate_c.IsDirty(DIRTY_VIEWPORTSCISSOR_STATE)) {
|
||||
ViewportAndScissor vpAndScissor;
|
||||
ConvertViewportAndScissor(framebufferManager_->UseBufferedRendering(),
|
||||
framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(),
|
||||
framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(),
|
||||
vpAndScissor);
|
||||
}
|
||||
|
||||
int maxIndex = indexGen.MaxIndex();
|
||||
SoftwareTransform swTransform(params);
|
||||
|
||||
// Half pixel offset hack.
|
||||
float xScale = gstate_c.vpWidth < 0 ? -1.0f : 1.0f;
|
||||
float xOffset = -1.0f / gstate_c.curRTRenderWidth;
|
||||
float yScale = gstate_c.vpHeight > 0 ? -1.0f : 1.0f;
|
||||
float yOffset = 1.0f / gstate_c.curRTRenderHeight;
|
||||
|
||||
const Lin::Vec3 trans(gstate_c.vpXOffset * xScale + xOffset, gstate_c.vpYOffset * yScale + yOffset, gstate_c.vpZOffset * 0.5f + 0.5f);
|
||||
const Lin::Vec3 scale(gstate_c.vpWidthScale, gstate_c.vpHeightScale, gstate_c.vpDepthScale * 0.5f);
|
||||
swTransform.SetProjMatrix(gstate.projMatrix, gstate_c.vpWidth < 0, gstate_c.vpHeight > 0, trans, scale);
|
||||
|
||||
swTransform.Decode(prim, dec_->VertexType(), dec_->GetDecVtxFmt(), maxIndex, &result);
|
||||
if (result.action == SW_NOT_READY) {
|
||||
swTransform.DetectOffsetTexture(maxIndex);
|
||||
|
||||
@@ -22,13 +22,14 @@
|
||||
#include <cmath>
|
||||
#include <map>
|
||||
|
||||
#include "Common/Data/Convert/SmallDataConvert.h"
|
||||
#include "Common/Data/Encoding/Utf8.h"
|
||||
#include "Common/Data/Text/I18n.h"
|
||||
#include "Common/Math/lin/matrix4x4.h"
|
||||
#include "Common/Math/math_util.h"
|
||||
#include "Common/Data/Convert/SmallDataConvert.h"
|
||||
#include "Common/GPU/D3D9/D3D9ShaderCompiler.h"
|
||||
#include "Common/GPU/thin3d.h"
|
||||
#include "Common/Data/Encoding/Utf8.h"
|
||||
#include "Common/System/Display.h"
|
||||
|
||||
#include "Common/Common.h"
|
||||
#include "Common/Log.h"
|
||||
@@ -344,6 +345,7 @@ void ShaderManagerDX9::VSUpdateUniforms(u64 dirtyUniforms) {
|
||||
ConvertProjMatrixToD3D(flippedMatrix, invertedX, invertedY);
|
||||
|
||||
VSSetMatrix(CONST_VS_PROJ, flippedMatrix.getReadPtr());
|
||||
VSSetFloat(CONST_VS_ROTATION, (float)g_display_rotation);
|
||||
}
|
||||
if (dirtyUniforms & DIRTY_PROJTHROUGHMATRIX) {
|
||||
Matrix4x4 proj_through;
|
||||
|
||||
@@ -118,10 +118,11 @@ void DrawEngineGLES::InitDeviceObjects() {
|
||||
|
||||
int vertexSize = sizeof(TransformedVertex);
|
||||
std::vector<GLRInputLayout::Entry> entries;
|
||||
entries.push_back({ ATTR_POSITION, 4, GL_FLOAT, GL_FALSE, vertexSize, 0 });
|
||||
entries.push_back({ ATTR_POSITION, 4, GL_FLOAT, GL_FALSE, vertexSize, offsetof(TransformedVertex, x) });
|
||||
entries.push_back({ ATTR_TEXCOORD, 3, GL_FLOAT, GL_FALSE, vertexSize, offsetof(TransformedVertex, u) });
|
||||
entries.push_back({ ATTR_COLOR0, 4, GL_UNSIGNED_BYTE, GL_TRUE, vertexSize, offsetof(TransformedVertex, color0) });
|
||||
entries.push_back({ ATTR_COLOR1, 3, GL_UNSIGNED_BYTE, GL_TRUE, vertexSize, offsetof(TransformedVertex, color1) });
|
||||
entries.push_back({ ATTR_NORMAL, 1, GL_FLOAT, GL_FALSE, vertexSize, offsetof(TransformedVertex, fog) });
|
||||
softwareInputLayout_ = render_->CreateInputLayout(entries);
|
||||
}
|
||||
|
||||
@@ -563,6 +564,15 @@ void DrawEngineGLES::DoFlush() {
|
||||
params.allowClear = true;
|
||||
params.allowSeparateAlphaClear = true;
|
||||
params.provokeFlatFirst = false;
|
||||
params.flippedY = framebufferManager_->UseBufferedRendering();
|
||||
|
||||
// We need correct viewport values in gstate_c already.
|
||||
if (gstate_c.IsDirty(DIRTY_VIEWPORTSCISSOR_STATE)) {
|
||||
ConvertViewportAndScissor(framebufferManager_->UseBufferedRendering(),
|
||||
framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(),
|
||||
framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(),
|
||||
vpAndScissor);
|
||||
}
|
||||
|
||||
int maxIndex = indexGen.MaxIndex();
|
||||
int vertexCount = indexGen.VertexCount();
|
||||
@@ -574,6 +584,12 @@ void DrawEngineGLES::DoFlush() {
|
||||
#endif
|
||||
|
||||
SoftwareTransform swTransform(params);
|
||||
|
||||
const Lin::Vec3 trans(gstate_c.vpXOffset, gstate_c.vpYOffset, gstate_c.vpZOffset);
|
||||
const Lin::Vec3 scale(gstate_c.vpWidthScale, gstate_c.vpHeightScale * (params.flippedY ? 1.0 : -1.0f), gstate_c.vpDepthScale);
|
||||
const bool invertedY = gstate_c.vpHeight * (params.flippedY ? 1.0 : -1.0f) < 0;
|
||||
swTransform.SetProjMatrix(gstate.projMatrix, gstate_c.vpWidth < 0, invertedY, trans, scale);
|
||||
|
||||
swTransform.Decode(prim, dec_->VertexType(), dec_->GetDecVtxFmt(), maxIndex, &result);
|
||||
if (result.action == SW_NOT_READY)
|
||||
swTransform.DetectOffsetTexture(maxIndex);
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "Common/GPU/Shader.h"
|
||||
#include "Common/GPU/thin3d.h"
|
||||
#include "Common/GPU/OpenGL/GLRenderManager.h"
|
||||
#include "Common/System/Display.h"
|
||||
|
||||
#include "Common/Log.h"
|
||||
#include "Common/File/FileUtil.h"
|
||||
@@ -84,7 +85,10 @@ LinkedShader::LinkedShader(GLRenderManager *render, VShaderID VSID, Shader *vs,
|
||||
std::vector<GLRProgram::Semantic> semantics;
|
||||
semantics.push_back({ ATTR_POSITION, "position" });
|
||||
semantics.push_back({ ATTR_TEXCOORD, "texcoord" });
|
||||
semantics.push_back({ ATTR_NORMAL, "normal" });
|
||||
if (useHWTransform_)
|
||||
semantics.push_back({ ATTR_NORMAL, "normal" });
|
||||
else
|
||||
semantics.push_back({ ATTR_NORMAL, "fog" });
|
||||
semantics.push_back({ ATTR_W1, "w1" });
|
||||
semantics.push_back({ ATTR_W2, "w2" });
|
||||
semantics.push_back({ ATTR_COLOR0, "color0" });
|
||||
@@ -124,6 +128,7 @@ LinkedShader::LinkedShader(GLRenderManager *render, VShaderID VSID, Shader *vs,
|
||||
queries.push_back({ &u_depthRange, "u_depthRange" });
|
||||
queries.push_back({ &u_cullRangeMin, "u_cullRangeMin" });
|
||||
queries.push_back({ &u_cullRangeMax, "u_cullRangeMax" });
|
||||
queries.push_back({ &u_rotation, "u_rotation" });
|
||||
|
||||
#ifdef USE_BONE_ARRAY
|
||||
queries.push_back({ &u_bone, "u_bone" });
|
||||
@@ -360,6 +365,7 @@ void LinkedShader::UpdateUniforms(u32 vertType, const ShaderID &vsid, bool useBu
|
||||
ScaleProjMatrix(flippedMatrix, useBufferedRendering);
|
||||
|
||||
render_->SetUniformM4x4(&u_proj, flippedMatrix.m);
|
||||
render_->SetUniformF1(&u_rotation, (float)g_display_rotation);
|
||||
}
|
||||
if (dirty & DIRTY_PROJTHROUGHMATRIX)
|
||||
{
|
||||
|
||||
@@ -60,6 +60,7 @@ public:
|
||||
int u_depthRange; // x,y = viewport xscale/xcenter. z,w=clipping minz/maxz (?)
|
||||
int u_cullRangeMin;
|
||||
int u_cullRangeMax;
|
||||
int u_rotation;
|
||||
|
||||
#ifdef USE_BONE_ARRAY
|
||||
int u_bone; // array, size is numBones
|
||||
|
||||
@@ -2259,6 +2259,7 @@ void GPUCommon::Execute_ImmVertexAlphaPrim(u32 op, u32 diff) {
|
||||
v.x = ((gstate.imm_vscx & 0xFFFFFF) - offsetX) / 16.0f;
|
||||
v.y = ((gstate.imm_vscy & 0xFFFFFF) - offsetY) / 16.0f;
|
||||
v.z = gstate.imm_vscz & 0xFFFF;
|
||||
v.posw = 1.0f;
|
||||
v.u = getFloat24(gstate.imm_vtcs);
|
||||
v.v = getFloat24(gstate.imm_vtct);
|
||||
v.w = getFloat24(gstate.imm_vtcq);
|
||||
|
||||
+2
-1
@@ -43,7 +43,7 @@ enum {
|
||||
struct TransformedVertex {
|
||||
union {
|
||||
struct {
|
||||
float x, y, z, fog; // in case of morph, preblend during decode
|
||||
float x, y, z, posw; // in case of morph, preblend during decode
|
||||
};
|
||||
float pos[4];
|
||||
};
|
||||
@@ -53,6 +53,7 @@ struct TransformedVertex {
|
||||
};
|
||||
float uv[3];
|
||||
};
|
||||
float fog;
|
||||
union {
|
||||
u8 color0[4]; // prelit
|
||||
u32 color0_32;
|
||||
|
||||
@@ -909,17 +909,26 @@ void DrawEngineVulkan::DoFlush() {
|
||||
params.allowClear = framebufferManager_->UseBufferedRendering();
|
||||
params.allowSeparateAlphaClear = false;
|
||||
params.provokeFlatFirst = true;
|
||||
params.flippedY = true;
|
||||
|
||||
// We need to update the viewport early because it's checked for flipping in SoftwareTransform.
|
||||
// We don't have a "DrawStateEarly" in vulkan, so...
|
||||
// TODO: Probably should eventually refactor this and feed the vp size into SoftwareTransform directly (Unknown's idea).
|
||||
if (gstate_c.IsDirty(DIRTY_VIEWPORTSCISSOR_STATE)) {
|
||||
gstate_c.vpWidth = gstate.getViewportXScale() * 2.0f;
|
||||
gstate_c.vpHeight = gstate.getViewportYScale() * 2.0f;
|
||||
ViewportAndScissor vpAndScissor;
|
||||
ConvertViewportAndScissor(framebufferManager_->UseBufferedRendering(),
|
||||
framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(),
|
||||
framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(),
|
||||
vpAndScissor);
|
||||
}
|
||||
|
||||
int maxIndex = indexGen.MaxIndex();
|
||||
SoftwareTransform swTransform(params);
|
||||
|
||||
const Lin::Vec3 trans(gstate_c.vpXOffset, gstate_c.vpYOffset, gstate_c.vpZOffset * 0.5f + 0.5f);
|
||||
const Lin::Vec3 scale(gstate_c.vpWidthScale, gstate_c.vpHeightScale, gstate_c.vpDepthScale * 0.5f);
|
||||
swTransform.SetProjMatrix(gstate.projMatrix, gstate_c.vpWidth < 0, gstate_c.vpHeight < 0, trans, scale);
|
||||
|
||||
swTransform.Decode(prim, dec_->VertexType(), dec_->GetDecVtxFmt(), maxIndex, &result);
|
||||
if (result.action == SW_NOT_READY) {
|
||||
swTransform.DetectOffsetTexture(maxIndex);
|
||||
|
||||
@@ -115,15 +115,18 @@ static int SetupVertexAttribs(VkVertexInputAttributeDescription attrs[], const D
|
||||
return count;
|
||||
}
|
||||
|
||||
static int SetupVertexAttribsPretransformed(VkVertexInputAttributeDescription attrs[], bool needsUV, bool needsColor1) {
|
||||
static int SetupVertexAttribsPretransformed(VkVertexInputAttributeDescription attrs[], bool needsUV, bool needsColor1, bool needsFog) {
|
||||
int count = 0;
|
||||
VertexAttribSetup(&attrs[count++], DEC_FLOAT_4, 0, PspAttributeLocation::POSITION);
|
||||
VertexAttribSetup(&attrs[count++], DEC_FLOAT_4, offsetof(TransformedVertex, pos), PspAttributeLocation::POSITION);
|
||||
if (needsUV) {
|
||||
VertexAttribSetup(&attrs[count++], DEC_FLOAT_3, 16, PspAttributeLocation::TEXCOORD);
|
||||
VertexAttribSetup(&attrs[count++], DEC_FLOAT_3, offsetof(TransformedVertex, uv), PspAttributeLocation::TEXCOORD);
|
||||
}
|
||||
VertexAttribSetup(&attrs[count++], DEC_U8_4, 28, PspAttributeLocation::COLOR0);
|
||||
VertexAttribSetup(&attrs[count++], DEC_U8_4, offsetof(TransformedVertex, color0), PspAttributeLocation::COLOR0);
|
||||
if (needsColor1) {
|
||||
VertexAttribSetup(&attrs[count++], DEC_U8_4, 32, PspAttributeLocation::COLOR1);
|
||||
VertexAttribSetup(&attrs[count++], DEC_U8_4, offsetof(TransformedVertex, color1), PspAttributeLocation::COLOR1);
|
||||
}
|
||||
if (needsFog) {
|
||||
VertexAttribSetup(&attrs[count++], DEC_FLOAT_1, offsetof(TransformedVertex, fog), PspAttributeLocation::NORMAL);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
@@ -276,8 +279,9 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip
|
||||
} else {
|
||||
bool needsUV = vs->GetID().Bit(VS_BIT_DO_TEXTURE);
|
||||
bool needsColor1 = vs->GetID().Bit(VS_BIT_LMODE);
|
||||
attributeCount = SetupVertexAttribsPretransformed(attrs, needsUV, needsColor1);
|
||||
vertexStride = 36;
|
||||
bool needsFog = vs->GetID().Bit(VS_BIT_ENABLE_FOG);
|
||||
attributeCount = SetupVertexAttribsPretransformed(attrs, needsUV, needsColor1, needsFog);
|
||||
vertexStride = (int)sizeof(TransformedVertex);
|
||||
}
|
||||
|
||||
VkVertexInputBindingDescription ibd{};
|
||||
|
||||
Reference in new issue
Block a user