mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-12 00:59:41 +01:00
Merge pull request #9384 from xebra/hw_tess_dx11
Hardware tessellation on D3D11.
This commit is contained in:
commit
91ebdf0213
8 files changed
+371
-38
No files matched your search
@@ -189,7 +189,7 @@ void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipView
|
||||
|
||||
if (gstate_c.bezier) {
|
||||
if (dirtyUniforms & DIRTY_BEZIERCOUNTU)
|
||||
ub->spline_count_u = gstate_c.bezier_count_u;
|
||||
ub->spline_count_u = gstate_c.spline_count_u;
|
||||
} else if (gstate_c.spline) {
|
||||
if (dirtyUniforms & DIRTY_SPLINECOUNTU)
|
||||
ub->spline_count_u = gstate_c.spline_count_u;
|
||||
|
||||
@@ -80,10 +80,10 @@ R"( float4x4 u_proj;
|
||||
float4 u_depthRange;
|
||||
float3 u_fogcoef_stencilreplace;
|
||||
float4 u_matambientalpha;
|
||||
int spline_count_u;
|
||||
int spline_count_v;
|
||||
int spline_type_u;
|
||||
int spline_type_v;
|
||||
int u_spline_count_u;
|
||||
int u_spline_count_v;
|
||||
int u_spline_type_u;
|
||||
int u_spline_type_v;
|
||||
float3 u_fogcolor;
|
||||
float3 u_texenv;
|
||||
uint4 u_alphacolorref;
|
||||
|
||||
@@ -123,7 +123,7 @@ void DrawEngineD3D11::InitDeviceObjects() {
|
||||
pushVerts_ = new PushBufferD3D11(device_, VERTEX_PUSH_SIZE, D3D11_BIND_VERTEX_BUFFER);
|
||||
pushInds_ = new PushBufferD3D11(device_, INDEX_PUSH_SIZE, D3D11_BIND_INDEX_BUFFER);
|
||||
|
||||
tessDataTransfer = new TessellationDataTransferD3D11();
|
||||
tessDataTransfer = new TessellationDataTransferD3D11(context_, device_);
|
||||
}
|
||||
|
||||
void DrawEngineD3D11::ClearTrackedVertexArrays() {
|
||||
@@ -796,7 +796,10 @@ rotateVBO:
|
||||
memcpy(iptr, decIndex, iSize);
|
||||
pushInds_->EndPush(context_);
|
||||
context_->IASetIndexBuffer(pushInds_->Buf(), DXGI_FORMAT_R16_UINT, iOffset);
|
||||
context_->DrawIndexed(vertexCount, 0, 0);
|
||||
if (gstate_c.bezier || gstate_c.spline)
|
||||
context_->DrawIndexedInstanced(vertexCount, numPatches, 0, 0, 0);
|
||||
else
|
||||
context_->DrawIndexed(vertexCount, 0, 0);
|
||||
} else {
|
||||
context_->Draw(vertexCount, 0);
|
||||
}
|
||||
@@ -805,7 +808,10 @@ rotateVBO:
|
||||
context_->IASetVertexBuffers(0, 1, &vb_, &stride, &offset);
|
||||
if (useElements) {
|
||||
context_->IASetIndexBuffer(ib_, DXGI_FORMAT_R16_UINT, 0);
|
||||
context_->DrawIndexed(vertexCount, 0, 0);
|
||||
if (gstate_c.bezier || gstate_c.spline)
|
||||
context_->DrawIndexedInstanced(vertexCount, numPatches, 0, 0, 0);
|
||||
else
|
||||
context_->DrawIndexed(vertexCount, 0, 0);
|
||||
} else {
|
||||
context_->Draw(vertexCount, 0);
|
||||
}
|
||||
@@ -961,7 +967,70 @@ bool DrawEngineD3D11::IsCodePtrVertexDecoder(const u8 *ptr) const {
|
||||
return decJitCache_->IsInSpace(ptr);
|
||||
}
|
||||
|
||||
void DrawEngineD3D11::TessellationDataTransferD3D11::SendDataToShader(const float * pos, const float * tex, const float * col, int size, bool hasColor, bool hasTexCoords)
|
||||
{
|
||||
// HW tessellation not yet supported
|
||||
void DrawEngineD3D11::TessellationDataTransferD3D11::SendDataToShader(const float * pos, const float * tex, const float * col, int size, bool hasColor, bool hasTexCoords) {
|
||||
// Position
|
||||
if (prevSize < size) {
|
||||
prevSize = size;
|
||||
if (data_tex[0]) {
|
||||
data_tex[0]->Release();
|
||||
view[0]->Release();
|
||||
}
|
||||
desc.Width = size;
|
||||
desc.Format = DXGI_FORMAT_R32G32B32_FLOAT;
|
||||
HRESULT hr = device_->CreateTexture1D(&desc, nullptr, &data_tex[0]);
|
||||
if (FAILED(hr)) {
|
||||
INFO_LOG(G3D, "Failed to create D3D texture for HW tessellation");
|
||||
data_tex[0]->Release();
|
||||
return; // TODO: Turn off HW tessellation if texture creation error occured.
|
||||
}
|
||||
hr = device_->CreateShaderResourceView(data_tex[0], nullptr, &view[0]);
|
||||
context_->VSSetShaderResources(0, 1, &view[0]);
|
||||
}
|
||||
dstBox.right = size;
|
||||
context_->UpdateSubresource(data_tex[0], 0, &dstBox, pos, 0, 0);
|
||||
|
||||
// Texcoords
|
||||
if (hasTexCoords) {
|
||||
if (prevSizeTex < size) {
|
||||
prevSizeTex = size;
|
||||
if (data_tex[1]) {
|
||||
data_tex[1]->Release();
|
||||
view[1]->Release();
|
||||
}
|
||||
desc.Width = size;
|
||||
desc.Format = DXGI_FORMAT_R32G32B32_FLOAT;
|
||||
HRESULT hr = device_->CreateTexture1D(&desc, nullptr, &data_tex[1]);
|
||||
if (FAILED(hr)) {
|
||||
INFO_LOG(G3D, "Failed to create D3D texture for HW tessellation");
|
||||
data_tex[1]->Release();
|
||||
return;
|
||||
}
|
||||
hr = device_->CreateShaderResourceView(data_tex[1], nullptr, &view[1]);
|
||||
context_->VSSetShaderResources(1, 1, &view[1]);
|
||||
}
|
||||
dstBox.right = size;
|
||||
context_->UpdateSubresource(data_tex[1], 0, &dstBox, tex, 0, 0);
|
||||
}
|
||||
|
||||
// Color
|
||||
int sizeColor = hasColor ? size : 1;
|
||||
if (prevSizeCol < sizeColor) {
|
||||
prevSizeCol = sizeColor;
|
||||
if (data_tex[2]) {
|
||||
data_tex[2]->Release();
|
||||
view[2]->Release();
|
||||
}
|
||||
desc.Width = sizeColor;
|
||||
desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
HRESULT hr = device_->CreateTexture1D(&desc, nullptr, &data_tex[2]);
|
||||
if (FAILED(hr)) {
|
||||
INFO_LOG(G3D, "Failed to create D3D texture for HW tessellation");
|
||||
data_tex[2]->Release();
|
||||
return;
|
||||
}
|
||||
hr = device_->CreateShaderResourceView(data_tex[2], nullptr, &view[2]);
|
||||
context_->VSSetShaderResources(2, 1, &view[2]);
|
||||
}
|
||||
dstBox.right = sizeColor;
|
||||
context_->UpdateSubresource(data_tex[2], 0, &dstBox, col, 0, 0);
|
||||
}
|
||||
@@ -256,11 +256,28 @@ private:
|
||||
// Hardware tessellation
|
||||
class TessellationDataTransferD3D11 : public TessellationDataTransfer {
|
||||
private:
|
||||
int data_tex[3];
|
||||
ID3D11DeviceContext *context_;
|
||||
ID3D11Device *device_;
|
||||
ID3D11Texture1D *data_tex[3];
|
||||
ID3D11ShaderResourceView *view[3];
|
||||
D3D11_TEXTURE1D_DESC desc;
|
||||
D3D11_BOX dstBox;
|
||||
public:
|
||||
TessellationDataTransferD3D11() : TessellationDataTransfer(), data_tex() {
|
||||
TessellationDataTransferD3D11(ID3D11DeviceContext *context_, ID3D11Device *device_)
|
||||
: TessellationDataTransfer(), context_(context_), device_(device_), data_tex(), view(), desc(), dstBox{0, 0, 0, 1, 1, 1} {
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.ArraySize = 1;
|
||||
desc.MipLevels = 1;
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
}
|
||||
~TessellationDataTransferD3D11() {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (data_tex[i]) {
|
||||
data_tex[i]->Release();
|
||||
view[i]->Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
void SendDataToShader(const float *pos, const float *tex, const float *col, int size, bool hasColor, bool hasTexCoords) override;
|
||||
};
|
||||
|
||||
+40
-5
@@ -477,11 +477,13 @@ GPU_D3D11::GPU_D3D11(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
|
||||
textureCache_->NotifyConfigChanged();
|
||||
|
||||
if (g_Config.bHardwareTessellation) {
|
||||
// Disable hardware tessellation bacause DX11 is still unsupported.
|
||||
g_Config.bHardwareTessellation = false;
|
||||
ERROR_LOG(G3D, "Hardware Tessellation is unsupported, falling back to software tessellation");
|
||||
I18NCategory *gr = GetI18NCategory("Graphics");
|
||||
host->NotifyUserMessage(gr->T("Turn off Hardware Tessellation - unsupported"), 2.5f, 0xFF3030FF);
|
||||
if (false) { // TODO: Check GPU features
|
||||
// Disable hardware tessellation.
|
||||
g_Config.bHardwareTessellation = false;
|
||||
ERROR_LOG(G3D, "Hardware Tessellation is unsupported, falling back to software tessellation");
|
||||
I18NCategory *gr = GetI18NCategory("Graphics");
|
||||
host->NotifyUserMessage(gr->T("Turn off Hardware Tessellation - unsupported"), 2.5f, 0xFF3030FF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -874,9 +876,20 @@ void GPU_D3D11::Execute_Bezier(u32 op, u32 diff) {
|
||||
int bz_vcount = (op >> 8) & 0xFF;
|
||||
bool computeNormals = gstate.isLightingEnabled();
|
||||
bool patchFacing = gstate.patchfacing & 1;
|
||||
|
||||
if (g_Config.bHardwareTessellation && g_Config.bHardwareTransform && !g_Config.bSoftwareRendering) {
|
||||
gstate_c.bezier = true;
|
||||
if (gstate_c.spline_count_u != bz_ucount) {
|
||||
gstate_c.Dirty(DIRTY_BEZIERCOUNTU);
|
||||
gstate_c.spline_count_u = bz_ucount;
|
||||
}
|
||||
}
|
||||
|
||||
int bytesRead = 0;
|
||||
drawEngine_.SubmitBezier(control_points, indices, gstate.getPatchDivisionU(), gstate.getPatchDivisionV(), bz_ucount, bz_vcount, patchPrim, computeNormals, patchFacing, gstate.vertType, &bytesRead);
|
||||
|
||||
gstate_c.bezier = false;
|
||||
|
||||
// After drawing, we advance pointers - see SubmitPrim which does the same.
|
||||
int count = bz_ucount * bz_vcount;
|
||||
AdvanceVerts(gstate.vertType, count, bytesRead);
|
||||
@@ -922,9 +935,31 @@ void GPU_D3D11::Execute_Spline(u32 op, u32 diff) {
|
||||
bool computeNormals = gstate.isLightingEnabled();
|
||||
bool patchFacing = gstate.patchfacing & 1;
|
||||
u32 vertType = gstate.vertType;
|
||||
|
||||
if (g_Config.bHardwareTessellation && g_Config.bHardwareTransform && !g_Config.bSoftwareRendering) {
|
||||
gstate_c.spline = true;
|
||||
if (gstate_c.spline_count_u != sp_ucount) {
|
||||
gstate_c.Dirty(DIRTY_SPLINECOUNTU);
|
||||
gstate_c.spline_count_u = sp_ucount;
|
||||
}
|
||||
if (gstate_c.spline_count_v != sp_vcount) {
|
||||
gstate_c.Dirty(DIRTY_SPLINECOUNTV);
|
||||
gstate_c.spline_count_v = sp_vcount;
|
||||
}
|
||||
if (gstate_c.spline_type_u != sp_utype) {
|
||||
gstate_c.Dirty(DIRTY_SPLINETYPEU);
|
||||
gstate_c.spline_type_u = sp_utype;
|
||||
}
|
||||
if (gstate_c.spline_type_v != sp_vtype) {
|
||||
gstate_c.Dirty(DIRTY_SPLINETYPEV);
|
||||
gstate_c.spline_type_v = sp_vtype;
|
||||
}
|
||||
}
|
||||
int bytesRead = 0;
|
||||
drawEngine_.SubmitSpline(control_points, indices, gstate.getPatchDivisionU(), gstate.getPatchDivisionV(), sp_ucount, sp_vcount, sp_utype, sp_vtype, patchPrim, computeNormals, patchFacing, vertType, &bytesRead);
|
||||
|
||||
gstate_c.spline = false;
|
||||
|
||||
// After drawing, we advance pointers - see SubmitPrim which does the same.
|
||||
int count = sp_ucount * sp_vcount;
|
||||
AdvanceVerts(gstate.vertType, count, bytesRead);
|
||||
|
||||
@@ -84,6 +84,12 @@ void GenerateVertexShaderHLSL(const ShaderID &id, char *buffer, ShaderLanguage l
|
||||
bool enableLighting = id.Bit(VS_BIT_LIGHTING_ENABLE);
|
||||
int matUpdate = id.Bits(VS_BIT_MATERIAL_UPDATE, 3);
|
||||
|
||||
bool doBezier = id.Bit(VS_BIT_BEZIER);
|
||||
bool doSpline = id.Bit(VS_BIT_SPLINE);
|
||||
bool hasColorTess = id.Bit(VS_BIT_HAS_COLOR_TESS);
|
||||
bool hasTexcoordTess = id.Bit(VS_BIT_HAS_TEXCOORD_TESS);
|
||||
bool flipNormalTess = id.Bit(VS_BIT_NORM_REVERSE_TESS);
|
||||
|
||||
bool scaleUV = !throughmode && (uvGenMode == GE_TEXMAP_TEXTURE_COORDS || uvGenMode == GE_TEXMAP_UNKNOWN);
|
||||
|
||||
DoLightComputation doLight[4] = { LIGHT_OFF, LIGHT_OFF, LIGHT_OFF, LIGHT_OFF };
|
||||
@@ -185,6 +191,9 @@ void GenerateVertexShaderHLSL(const ShaderID &id, char *buffer, ShaderLanguage l
|
||||
bool texCoordInVec3 = false;
|
||||
if (useHWTransform) {
|
||||
WRITE(p, "struct VS_IN { \n");
|
||||
if ((doSpline || doBezier) && lang == HLSL_D3D11) {
|
||||
WRITE(p, " uint instanceId : SV_InstanceID;\n");
|
||||
}
|
||||
if (enableBones) {
|
||||
WRITE(p, " %s", boneWeightAttrDecl[numBoneWeights]);
|
||||
}
|
||||
@@ -253,6 +262,88 @@ void GenerateVertexShaderHLSL(const ShaderID &id, char *buffer, ShaderLanguage l
|
||||
WRITE(p, "}\n\n");
|
||||
}
|
||||
|
||||
// Hardware tessellation
|
||||
if (doSpline || doBezier) {
|
||||
if (lang == HLSL_D3D11) {
|
||||
WRITE(p, "Texture1D<float3> u_tess_pos_tex : register(t0);\n");
|
||||
WRITE(p, "Texture1D<float3> u_tess_tex_tex : register(t1);\n");
|
||||
WRITE(p, "Texture1D<float4> u_tess_col_tex : register(t2);\n");
|
||||
}
|
||||
|
||||
const char *init[3] = { "0.0, 0.0", "0.0, 0.0, 0.0", "0.0, 0.0, 0.0, 0.0" };
|
||||
for (int i = 2; i <= 4; i++) {
|
||||
// Define 3 types float2, float3, float4
|
||||
WRITE(p, "float%d tess_sample(in float%d points[16], in float2 weights[4]) {\n", i, i);
|
||||
WRITE(p, " float%d pos = float%d(%s);\n", i, i, init[i - 2]);
|
||||
WRITE(p, " for (int i = 0; i < 4; ++i) {\n");
|
||||
WRITE(p, " for (int j = 0; j < 4; ++j) {\n");
|
||||
WRITE(p, " float f = weights[j].x * weights[i].y;\n");
|
||||
WRITE(p, " if (f != 0.0)\n");
|
||||
WRITE(p, " pos = pos + f * points[i * 4 + j];\n");
|
||||
WRITE(p, " }\n");
|
||||
WRITE(p, " }\n");
|
||||
WRITE(p, " return pos;\n");
|
||||
WRITE(p, "}\n");
|
||||
}
|
||||
if (doSpline) {
|
||||
WRITE(p, "void spline_knot(int2 num_patches, int2 type, out float2 knot[6], int2 patch_pos) {\n");
|
||||
WRITE(p, " for (int i = 0; i < 6; ++i) {\n");
|
||||
WRITE(p, " knot[i] = float2(i + patch_pos.x - 2, i + patch_pos.y - 2);\n");
|
||||
WRITE(p, " }\n");
|
||||
// WRITE(p, " if ((type.x & 1) != 0) {\n");
|
||||
WRITE(p, " if ((type.x == 1) || (type.x == 3)) {\n");
|
||||
WRITE(p, " if (patch_pos.x <= 2)\n");
|
||||
WRITE(p, " knot[0].x = 0.0;\n");
|
||||
WRITE(p, " if (patch_pos.x <= 1)\n");
|
||||
WRITE(p, " knot[1].x = 0.0;\n");
|
||||
WRITE(p, " }\n");
|
||||
// WRITE(p, " if ((type.x & 2) != 0) {\n");
|
||||
WRITE(p, " if ((type.x == 2) || (type.x == 3)) {\n");
|
||||
WRITE(p, " if (patch_pos.x >= (num_patches.x - 2))\n");
|
||||
WRITE(p, " knot[5].x = num_patches.x;\n");
|
||||
WRITE(p, " if (patch_pos.x == (num_patches.x - 1))\n");
|
||||
WRITE(p, " knot[4].x = num_patches.x;\n");
|
||||
WRITE(p, " }\n");
|
||||
// WRITE(p, " if ((type.y & 1) != 0) {\n");
|
||||
WRITE(p, " if ((type.y == 1) || (type.y == 3)) {\n");
|
||||
WRITE(p, " if (patch_pos.y <= 2)\n");
|
||||
WRITE(p, " knot[0].y = 0.0;\n");
|
||||
WRITE(p, " if (patch_pos.y <= 1)\n");
|
||||
WRITE(p, " knot[1].y = 0.0;\n");
|
||||
WRITE(p, " }\n");
|
||||
// WRITE(p, " if ((type.y & 2) != 0) {\n");
|
||||
WRITE(p, " if ((type.y == 2) || (type.y == 3)) {\n");
|
||||
WRITE(p, " if (patch_pos.y >= (num_patches.y - 2))\n");
|
||||
WRITE(p, " knot[5].y = num_patches.y;\n");
|
||||
WRITE(p, " if (patch_pos.y == (num_patches.y - 1))\n");
|
||||
WRITE(p, " knot[4].y = num_patches.y;\n");
|
||||
WRITE(p, " }\n");
|
||||
WRITE(p, "}\n");
|
||||
|
||||
WRITE(p, "void spline_weight(float2 t, in float2 knot[6], out float2 weights[4]) {\n");
|
||||
// TODO: Maybe compilers could be coaxed into vectorizing this code without the above explicitly...
|
||||
WRITE(p, " float2 t0 = (t - knot[0]);\n");
|
||||
WRITE(p, " float2 t1 = (t - knot[1]);\n");
|
||||
WRITE(p, " float2 t2 = (t - knot[2]);\n");
|
||||
// TODO: All our knots are integers so we should be able to get rid of these divisions (How?)
|
||||
WRITE(p, " float2 f30 = t0 / (knot[3] - knot[0]);\n");
|
||||
WRITE(p, " float2 f41 = t1 / (knot[4] - knot[1]);\n");
|
||||
WRITE(p, " float2 f52 = t2 / (knot[5] - knot[2]);\n");
|
||||
WRITE(p, " float2 f31 = t1 / (knot[3] - knot[1]);\n");
|
||||
WRITE(p, " float2 f42 = t2 / (knot[4] - knot[2]);\n");
|
||||
WRITE(p, " float2 f32 = t2 / (knot[3] - knot[2]);\n");
|
||||
WRITE(p, " float2 a = (1.0 - f30)*(1.0 - f31);\n");
|
||||
WRITE(p, " float2 b = (f31*f41);\n");
|
||||
WRITE(p, " float2 c = (1.0 - f41)*(1.0 - f42);\n");
|
||||
WRITE(p, " float2 d = (f42*f52);\n");
|
||||
WRITE(p, " weights[0] = a - (a*f32);\n");
|
||||
WRITE(p, " weights[1] = 1.0 - a - b + ((a + b + c - 1.0)*f32);\n");
|
||||
WRITE(p, " weights[2] = b + ((1.0 - b - c - d)*f32);\n");
|
||||
WRITE(p, " weights[3] = d*f32;\n");
|
||||
WRITE(p, "}\n");
|
||||
}
|
||||
}
|
||||
|
||||
WRITE(p, "VS_OUT main(VS_IN In) {\n");
|
||||
WRITE(p, " VS_OUT Out;\n");
|
||||
if (!useHWTransform) {
|
||||
@@ -300,12 +391,114 @@ void GenerateVertexShaderHLSL(const ShaderID &id, char *buffer, ShaderLanguage l
|
||||
} else {
|
||||
// Step 1: World Transform / Skinning
|
||||
if (!enableBones) {
|
||||
// No skinning, just standard T&L.
|
||||
WRITE(p, " float3 worldpos = mul(float4(In.position.xyz, 1.0), u_world);\n");
|
||||
if (hasNormal)
|
||||
WRITE(p, " float3 worldnormal = normalize(mul(float4(%sIn.normal, 0.0), u_world));\n", flipNormal ? "-" : "");
|
||||
else
|
||||
WRITE(p, " float3 worldnormal = float3(0.0, 0.0, 1.0);\n");
|
||||
// Hardware tessellation
|
||||
if (doSpline || doBezier) {
|
||||
WRITE(p, " uint num_patches_u = %s;\n", doBezier ? "(u_spline_count_u - 1) / 3u" : "u_spline_count_u - 3");
|
||||
WRITE(p, " float2 tess_pos = In.position.xy;\n");
|
||||
WRITE(p, " int u = In.instanceId %% num_patches_u;\n");
|
||||
WRITE(p, " int v = In.instanceId / num_patches_u;\n");
|
||||
WRITE(p, " int2 patch_pos = int2(u, v);\n");
|
||||
WRITE(p, " float3 _pos[16];\n");
|
||||
WRITE(p, " float2 _tex[16];\n");
|
||||
WRITE(p, " float4 _col[16];\n");
|
||||
WRITE(p, " int idx;\n");
|
||||
WRITE(p, " int2 index;\n");
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
WRITE(p, " idx = (%i + v%s) * u_spline_count_u + (%i + u%s);\n", i, doBezier ? " * 3" : "", j, doBezier ? " * 3" : "");
|
||||
WRITE(p, " index = int2(idx, 0);\n");
|
||||
WRITE(p, " _pos[%i] = u_tess_pos_tex.Load(index).xyz;\n", i * 4 + j);
|
||||
if (doTexture && hasTexcoord && hasTexcoordTess)
|
||||
WRITE(p, " _tex[%i] = u_tess_tex_tex.Load(index).xy;\n", i * 4 + j);
|
||||
if (hasColor && hasColorTess)
|
||||
WRITE(p, " _col[%i] = u_tess_col_tex.Load(index).rgba;\n", i * 4 + j);
|
||||
}
|
||||
}
|
||||
WRITE(p, " float2 weights[4];\n");
|
||||
if (doBezier) {
|
||||
// Bernstein 3D
|
||||
WRITE(p, " weights[0] = (1.0 - tess_pos) * (1.0 - tess_pos) * (1.0 - tess_pos);\n");
|
||||
WRITE(p, " weights[1] = 3.0 * tess_pos * (1.0 - tess_pos) * (1.0 - tess_pos);\n");
|
||||
WRITE(p, " weights[2] = 3.0 * tess_pos * tess_pos * (1.0 - tess_pos);\n");
|
||||
WRITE(p, " weights[3] = tess_pos * tess_pos * tess_pos;\n");
|
||||
} else if (doSpline) {
|
||||
WRITE(p, " int2 spline_num_patches = int2(u_spline_count_u - 3, u_spline_count_v - 3);\n");
|
||||
WRITE(p, " int2 spline_type = int2(u_spline_type_u, u_spline_type_v);\n");
|
||||
WRITE(p, " float2 knots[6];\n");
|
||||
WRITE(p, " spline_knot(spline_num_patches, spline_type, knots, patch_pos);\n");
|
||||
WRITE(p, " spline_weight(tess_pos + patch_pos, knots, weights);\n");
|
||||
}
|
||||
WRITE(p, " float3 pos = tess_sample(_pos, weights);\n");
|
||||
if (doTexture && hasTexcoord) {
|
||||
if (hasTexcoordTess)
|
||||
WRITE(p, " float2 tex = tess_sample(_tex, weights);\n");
|
||||
else
|
||||
WRITE(p, " float2 tex = tess_pos + patch_pos;\n");
|
||||
}
|
||||
if (hasColor) {
|
||||
if (hasColorTess)
|
||||
WRITE(p, " float4 col = tess_sample(_col, weights);\n");
|
||||
else
|
||||
WRITE(p, " float4 col = u_tess_col_tex.Load(int2(0, 0)).rgba;\n");
|
||||
}
|
||||
if (hasNormal) {
|
||||
// Curved surface is probably always need to compute normal(not sampling from control points)
|
||||
if (doBezier) {
|
||||
// Bernstein derivative
|
||||
WRITE(p, " float2 bernderiv[4];\n");
|
||||
WRITE(p, " bernderiv[0] = -3.0 * (tess_pos - 1.0) * (tess_pos - 1.0); \n");
|
||||
WRITE(p, " bernderiv[1] = 9.0 * tess_pos * tess_pos - 12.0 * tess_pos + 3.0; \n");
|
||||
WRITE(p, " bernderiv[2] = 3.0 * (2.0 - 3.0 * tess_pos) * tess_pos; \n");
|
||||
WRITE(p, " bernderiv[3] = 3.0 * tess_pos * tess_pos; \n");
|
||||
|
||||
WRITE(p, " float2 bernderiv_u[4];\n");
|
||||
WRITE(p, " float2 bernderiv_v[4];\n");
|
||||
WRITE(p, " for (int i = 0; i < 4; i++) {\n");
|
||||
WRITE(p, " bernderiv_u[i] = float2(bernderiv[i].x, weights[i].y);\n");
|
||||
WRITE(p, " bernderiv_v[i] = float2(weights[i].x, bernderiv[i].y);\n");
|
||||
WRITE(p, " }\n");
|
||||
|
||||
WRITE(p, " float3 du = tess_sample(_pos, bernderiv_u);\n");
|
||||
WRITE(p, " float3 dv = tess_sample(_pos, bernderiv_v);\n");
|
||||
} else if (doSpline) {
|
||||
WRITE(p, " float2 tess_next_u = float2(In.normal.x, 0.0);\n");
|
||||
WRITE(p, " float2 tess_next_v = float2(0.0, In.normal.y);\n");
|
||||
// Right
|
||||
WRITE(p, " float2 tess_pos_r = tess_pos + tess_next_u;\n");
|
||||
WRITE(p, " spline_weight(tess_pos_r + patch_pos, knots, weights);\n");
|
||||
WRITE(p, " float3 pos_r = tess_sample(_pos, weights);\n");
|
||||
// Left
|
||||
WRITE(p, " float2 tess_pos_l = tess_pos - tess_next_u;\n");
|
||||
WRITE(p, " spline_weight(tess_pos_l + patch_pos, knots, weights);\n");
|
||||
WRITE(p, " float3 pos_l = tess_sample(_pos, weights);\n");
|
||||
// Down
|
||||
WRITE(p, " float2 tess_pos_d = tess_pos + tess_next_v;\n");
|
||||
WRITE(p, " spline_weight(tess_pos_d + patch_pos, knots, weights);\n");
|
||||
WRITE(p, " float3 pos_d = tess_sample(_pos, weights);\n");
|
||||
// Up
|
||||
WRITE(p, " float2 tess_pos_u = tess_pos - tess_next_v;\n");
|
||||
WRITE(p, " spline_weight(tess_pos_u + patch_pos, knots, weights);\n");
|
||||
WRITE(p, " float3 pos_u = tess_sample(_pos, weights);\n");
|
||||
|
||||
WRITE(p, " float3 du = pos_r - pos_l;\n");
|
||||
WRITE(p, " float3 dv = pos_d - pos_u;\n");
|
||||
}
|
||||
WRITE(p, " float3 nrm = cross(du, dv);\n");
|
||||
WRITE(p, " nrm = normalize(nrm);\n");
|
||||
}
|
||||
WRITE(p, " float3 worldpos = mul(float4(pos.xyz, 1.0), u_world);\n");
|
||||
if (hasNormal)
|
||||
WRITE(p, " float3 worldnormal = normalize(mul(float4(%snrm, 0.0), u_world));\n", flipNormalTess ? "-" : "");
|
||||
else
|
||||
WRITE(p, " float3 worldnormal = float3(0.0, 0.0, 1.0);\n");
|
||||
} else {
|
||||
// No skinning, just standard T&L.
|
||||
WRITE(p, " float3 worldpos = mul(float4(In.position.xyz, 1.0), u_world);\n");
|
||||
if (hasNormal)
|
||||
WRITE(p, " float3 worldnormal = normalize(mul(float4(%sIn.normal, 0.0), u_world));\n", flipNormal ? "-" : "");
|
||||
else
|
||||
WRITE(p, " float3 worldnormal = float3(0.0, 0.0, 1.0);\n");
|
||||
}
|
||||
} else {
|
||||
static const char * const boneWeightAttr[8] = {
|
||||
"a_w1.x", "a_w1.y", "a_w1.z", "a_w1.w",
|
||||
@@ -399,6 +592,11 @@ void GenerateVertexShaderHLSL(const ShaderID &id, char *buffer, ShaderLanguage l
|
||||
const char *ambientStr = (gstate.materialupdate & 1) && hasColor ? "In.color0" : "u_matambientalpha";
|
||||
const char *diffuseStr = (gstate.materialupdate & 2) && hasColor ? "In.color0.rgb" : "u_matdiffuse";
|
||||
const char *specularStr = (gstate.materialupdate & 4) && hasColor ? "In.color0.rgb" : "u_matspecular.rgb";
|
||||
if (doBezier || doSpline) {
|
||||
ambientStr = (matUpdate & 1) && hasColor ? "col" : "u_matambientalpha";
|
||||
diffuseStr = (matUpdate & 2) && hasColor ? "col.rgb" : "u_matdiffuse";
|
||||
specularStr = (matUpdate & 4) && hasColor ? "col.rgb" : "u_matspecular.rgb";
|
||||
}
|
||||
|
||||
bool diffuseIsZero = true;
|
||||
bool specularIsZero = true;
|
||||
@@ -514,7 +712,10 @@ void GenerateVertexShaderHLSL(const ShaderID &id, char *buffer, ShaderLanguage l
|
||||
} else {
|
||||
// Lighting doesn't affect color.
|
||||
if (hasColor) {
|
||||
WRITE(p, " Out.v_color0 = In.color0;\n");
|
||||
if (doBezier || doSpline)
|
||||
WRITE(p, " Out.v_color0 = col;\n");
|
||||
else
|
||||
WRITE(p, " Out.v_color0 = In.color0;\n");
|
||||
} else {
|
||||
WRITE(p, " Out.v_color0 = u_matambientalpha;\n");
|
||||
}
|
||||
@@ -529,13 +730,19 @@ void GenerateVertexShaderHLSL(const ShaderID &id, char *buffer, ShaderLanguage l
|
||||
case GE_TEXMAP_UNKNOWN: // Not sure what this is, but Riviera uses it. Treating as coords works.
|
||||
if (scaleUV) {
|
||||
if (hasTexcoord) {
|
||||
WRITE(p, " Out.v_texcoord = float3(In.texcoord.xy * u_uvscaleoffset.xy, 0.0);\n");
|
||||
if (doBezier || doSpline)
|
||||
WRITE(p, " Out.v_texcoord = float3(tex.xy * u_uvscaleoffset.xy + u_uvscaleoffset.zw, 0.0);\n");
|
||||
else
|
||||
WRITE(p, " Out.v_texcoord = float3(In.texcoord.xy * u_uvscaleoffset.xy, 0.0);\n");
|
||||
} else {
|
||||
WRITE(p, " Out.v_texcoord = float3(0.0, 0.0, 0.0);\n");
|
||||
}
|
||||
} else {
|
||||
if (hasTexcoord) {
|
||||
WRITE(p, " Out.v_texcoord = float3(In.texcoord.xy * u_uvscaleoffset.xy + u_uvscaleoffset.zw, 0.0);\n");
|
||||
if (doBezier || doSpline)
|
||||
WRITE(p, " Out.v_texcoord = float3(tex.xy * u_uvscaleoffset.xy + u_uvscaleoffset.zw, 0.0);\n");
|
||||
else
|
||||
WRITE(p, " Out.v_texcoord = float3(In.texcoord.xy * u_uvscaleoffset.xy + u_uvscaleoffset.zw, 0.0);\n");
|
||||
} else {
|
||||
WRITE(p, " Out.v_texcoord = float3(u_uvscaleoffset.zw, 0.0);\n");
|
||||
}
|
||||
|
||||
@@ -879,9 +879,9 @@ void GPU_Vulkan::Execute_Bezier(u32 op, u32 diff) {
|
||||
|
||||
if (g_Config.bHardwareTessellation && g_Config.bHardwareTransform && !g_Config.bSoftwareRendering) {
|
||||
gstate_c.bezier = true;
|
||||
if (gstate_c.bezier_count_u != bz_ucount) {
|
||||
if (gstate_c.spline_count_u != bz_ucount) {
|
||||
gstate_c.Dirty(DIRTY_BEZIERCOUNTU);
|
||||
gstate_c.bezier_count_u = bz_ucount;
|
||||
gstate_c.spline_count_u = bz_ucount;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -99,6 +99,17 @@ bool CheckSupportInstancedTessellationGLES() {
|
||||
#endif
|
||||
}
|
||||
|
||||
bool IsBackendSupportHWTess() {
|
||||
switch (g_Config.iGPUBackend) {
|
||||
case GPU_BACKEND_OPENGL:
|
||||
return CheckSupportInstancedTessellationGLES();
|
||||
case GPU_BACKEND_VULKAN:
|
||||
case GPU_BACKEND_DIRECT3D11:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GameSettingsScreen::CreateViews() {
|
||||
GameInfo *info = g_gameInfoCache->GetInfo(NULL, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE);
|
||||
|
||||
@@ -312,9 +323,7 @@ void GameSettingsScreen::CreateViews() {
|
||||
bezierChoiceDisable_ = g_Config.bSoftwareRendering || g_Config.bHardwareTessellation;
|
||||
return UI::EVENT_CONTINUE;
|
||||
});
|
||||
bool isBackendSupportHWTess = g_Config.iGPUBackend == GPU_BACKEND_OPENGL || g_Config.iGPUBackend == GPU_BACKEND_VULKAN;
|
||||
bool isDeviceSupportInstTess = g_Config.iGPUBackend == GPU_BACKEND_OPENGL ? CheckSupportInstancedTessellationGLES() : isBackendSupportHWTess;
|
||||
tessHWEnable_ = isDeviceSupportInstTess && !g_Config.bSoftwareRendering && g_Config.bHardwareTransform;
|
||||
tessHWEnable_ = IsBackendSupportHWTess() && !g_Config.bSoftwareRendering && g_Config.bHardwareTransform;
|
||||
tessellationHW->SetEnabledPtr(&tessHWEnable_);
|
||||
|
||||
// In case we're going to add few other antialiasing option like MSAA in the future.
|
||||
@@ -754,17 +763,13 @@ UI::EventReturn GameSettingsScreen::OnSoftwareRendering(UI::EventParams &e) {
|
||||
postProcEnable_ = !g_Config.bSoftwareRendering && (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE);
|
||||
resolutionEnable_ = !g_Config.bSoftwareRendering && (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE);
|
||||
bezierChoiceDisable_ = g_Config.bSoftwareRendering || g_Config.bHardwareTessellation;
|
||||
bool isBackendSupportHWTess = g_Config.iGPUBackend == GPU_BACKEND_OPENGL || g_Config.iGPUBackend == GPU_BACKEND_VULKAN;
|
||||
bool isDeviceSupportInstTess = g_Config.iGPUBackend == GPU_BACKEND_OPENGL ? CheckSupportInstancedTessellationGLES() : isBackendSupportHWTess;
|
||||
tessHWEnable_ = isDeviceSupportInstTess && !g_Config.bSoftwareRendering && g_Config.bHardwareTransform;
|
||||
tessHWEnable_ = IsBackendSupportHWTess() && !g_Config.bSoftwareRendering && g_Config.bHardwareTransform;
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
UI::EventReturn GameSettingsScreen::OnHardwareTransform(UI::EventParams &e) {
|
||||
vtxCacheEnable_ = !g_Config.bSoftwareRendering && g_Config.bHardwareTransform;
|
||||
bool isBackendSupportHWTess = g_Config.iGPUBackend == GPU_BACKEND_OPENGL || g_Config.iGPUBackend == GPU_BACKEND_VULKAN;
|
||||
bool isDeviceSupportInstTess = g_Config.iGPUBackend == GPU_BACKEND_OPENGL ? CheckSupportInstancedTessellationGLES() : isBackendSupportHWTess;
|
||||
tessHWEnable_ = isDeviceSupportInstTess && !g_Config.bSoftwareRendering && g_Config.bHardwareTransform;
|
||||
tessHWEnable_ = IsBackendSupportHWTess() && !g_Config.bSoftwareRendering && g_Config.bHardwareTransform;
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user