Merge pull request #9384 from xebra/hw_tess_dx11

Hardware tessellation on D3D11.
This commit is contained in:
Henrik Rydgård authored and GitHub committed 2017-03-04 16:55:22 +01:00
commit 91ebdf0213
8 files changed
+371 -38

No files matched your search

+1 -1
View File
@@ -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;
+4 -4
View File
@@ -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;
+75 -6
View File
@@ -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);
}
+19 -2
View File
@@ -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
View File
@@ -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);
+216 -9
View File
@@ -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");
}
+2 -2
View File
@@ -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;
}
}
+14 -9
View File
@@ -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;
}