Skip to content

Commit

Permalink
GPU: Track HW tess at start of frame too.
Browse files Browse the repository at this point in the history
This also makes it so we don't force the setting off when you change
backends, and just ignore it if unsupported.
  • Loading branch information
unknownbrackets committed Apr 4, 2020
1 parent 46b9454 commit ac60e2e
Show file tree
Hide file tree
Showing 21 changed files with 52 additions and 30 deletions.
4 changes: 3 additions & 1 deletion GPU/Common/DrawEngineCommon.cpp
Expand Up @@ -38,6 +38,7 @@ DrawEngineCommon::DrawEngineCommon() : decoderMap_(16) {
transformed = (TransformedVertex *)AllocateMemoryPages(TRANSFORMED_VERTEX_BUFFER_SIZE, MEM_PROT_READ | MEM_PROT_WRITE);
transformedExpanded = (TransformedVertex *)AllocateMemoryPages(3 * TRANSFORMED_VERTEX_BUFFER_SIZE, MEM_PROT_READ | MEM_PROT_WRITE);
useHWTransform_ = g_Config.bHardwareTransform;
useHWTessellation_ = UpdateUseHWTessellation(g_Config.bHardwareTessellation);
}

DrawEngineCommon::~DrawEngineCommon() {
Expand Down Expand Up @@ -174,6 +175,7 @@ void DrawEngineCommon::Resized() {
ClearTrackedVertexArrays();

useHWTransform_ = g_Config.bHardwareTransform;
useHWTessellation_ = UpdateUseHWTessellation(g_Config.bHardwareTessellation);
}

u32 DrawEngineCommon::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType, int *vertexSize) {
Expand Down Expand Up @@ -747,7 +749,7 @@ bool DrawEngineCommon::CanUseHardwareTransform(int prim) {
}

bool DrawEngineCommon::CanUseHardwareTessellation(GEPatchPrimType prim) {
if (g_Config.bHardwareTessellation && !g_Config.bSoftwareRendering) {
if (useHWTessellation_) {
return CanUseHardwareTransform(PatchPrimToPrim(prim));
}
return false;
Expand Down
2 changes: 2 additions & 0 deletions GPU/Common/DrawEngineCommon.h
Expand Up @@ -104,6 +104,7 @@ class DrawEngineCommon {
VertexDecoder *GetVertexDecoder(u32 vtype);

protected:
virtual bool UpdateUseHWTessellation(bool enabled) { return enabled; }
virtual void ClearTrackedVertexArrays() {}

int ComputeNumVertsToDecode() const;
Expand Down Expand Up @@ -132,6 +133,7 @@ class DrawEngineCommon {
}

bool useHWTransform_ = false;
bool useHWTessellation_ = false;

// Vertex collector buffers
u8 *decoded = nullptr;
Expand Down
4 changes: 2 additions & 2 deletions GPU/Common/ShaderId.cpp
Expand Up @@ -60,7 +60,7 @@ std::string VertexShaderDesc(const VShaderID &id) {
return desc.str();
}

void ComputeVertexShaderID(VShaderID *id_out, u32 vertType, bool useHWTransform) {
void ComputeVertexShaderID(VShaderID *id_out, u32 vertType, bool useHWTransform, bool useHWTessellation) {
bool isModeThrough = (vertType & GE_VTYPE_THROUGH) != 0;
bool doTexture = gstate.isTextureMapEnabled() && !gstate.isModeClear();
bool doTextureTransform = gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX;
Expand Down Expand Up @@ -131,7 +131,7 @@ void ComputeVertexShaderID(VShaderID *id_out, u32 vertType, bool useHWTransform)
id.SetBit(VS_BIT_NORM_REVERSE, gstate.areNormalsReversed());
id.SetBit(VS_BIT_HAS_TEXCOORD, hasTexcoord);

if (g_Config.bHardwareTessellation) {
if (useHWTessellation) {
id.SetBit(VS_BIT_BEZIER, doBezier);
id.SetBit(VS_BIT_SPLINE, doSpline);
if (doBezier || doSpline) {
Expand Down
2 changes: 1 addition & 1 deletion GPU/Common/ShaderId.h
Expand Up @@ -223,7 +223,7 @@ class Bugs;
}


void ComputeVertexShaderID(VShaderID *id, uint32_t vertexType, bool useHWTransform);
void ComputeVertexShaderID(VShaderID *id, uint32_t vertexType, bool useHWTransform, bool useHWTessellation);
// Generates a compact string that describes the shader. Useful in a list to get an overview
// of the current flora of shaders.
std::string VertexShaderDesc(const VShaderID &id);
Expand Down
4 changes: 2 additions & 2 deletions GPU/D3D11/DrawEngineD3D11.cpp
Expand Up @@ -514,7 +514,7 @@ void DrawEngineD3D11::DoFlush() {

D3D11VertexShader *vshader;
D3D11FragmentShader *fshader;
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, useHWTransform);
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, useHWTransform, useHWTessellation_);
ID3D11InputLayout *inputLayout = SetupDecFmtForDraw(vshader, dec_->GetDecVtxFmt(), dec_->VertexType());
context_->PSSetShader(fshader->GetShader(), nullptr, 0);
context_->VSSetShader(vshader->GetShader(), nullptr, 0);
Expand Down Expand Up @@ -598,7 +598,7 @@ void DrawEngineD3D11::DoFlush() {

D3D11VertexShader *vshader;
D3D11FragmentShader *fshader;
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, false);
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, false, false);
context_->PSSetShader(fshader->GetShader(), nullptr, 0);
context_->VSSetShader(vshader->GetShader(), nullptr, 0);
shaderManager_->UpdateUniforms(framebufferManager_->UseBufferedRendering());
Expand Down
4 changes: 2 additions & 2 deletions GPU/D3D11/ShaderManagerD3D11.cpp
Expand Up @@ -178,13 +178,13 @@ void ShaderManagerD3D11::BindUniforms() {
context_->PSSetConstantBuffers(0, 1, ps_cbs);
}

void ShaderManagerD3D11::GetShaders(int prim, u32 vertType, D3D11VertexShader **vshader, D3D11FragmentShader **fshader, bool useHWTransform) {
void ShaderManagerD3D11::GetShaders(int prim, u32 vertType, D3D11VertexShader **vshader, D3D11FragmentShader **fshader, bool useHWTransform, bool useHWTessellation) {
VShaderID VSID;
FShaderID FSID;

if (gstate_c.IsDirty(DIRTY_VERTEXSHADER_STATE)) {
gstate_c.Clean(DIRTY_VERTEXSHADER_STATE);
ComputeVertexShaderID(&VSID, vertType, useHWTransform);
ComputeVertexShaderID(&VSID, vertType, useHWTransform, useHWTessellation);
} else {
VSID = lastVSID_;
}
Expand Down
2 changes: 1 addition & 1 deletion GPU/D3D11/ShaderManagerD3D11.h
Expand Up @@ -84,7 +84,7 @@ class ShaderManagerD3D11 : public ShaderManagerCommon {
ShaderManagerD3D11(Draw::DrawContext *draw, ID3D11Device *device, ID3D11DeviceContext *context, D3D_FEATURE_LEVEL featureLevel);
~ShaderManagerD3D11();

void GetShaders(int prim, u32 vertType, D3D11VertexShader **vshader, D3D11FragmentShader **fshader, bool useHWTransform);
void GetShaders(int prim, u32 vertType, D3D11VertexShader **vshader, D3D11FragmentShader **fshader, bool useHWTransform, bool useHWTessellation);
void ClearShaders();
void DirtyLastShader() override;

Expand Down
6 changes: 3 additions & 3 deletions GPU/Directx9/DrawEngineDX9.cpp
Expand Up @@ -310,7 +310,7 @@ void DrawEngineDX9::DoFlush() {
GEPrimitiveType prim = prevPrim_;
ApplyDrawState(prim);

VSShader *vshader = shaderManager_->ApplyShader(CanUseHardwareTransform(prim), lastVType_);
VSShader *vshader = shaderManager_->ApplyShader(CanUseHardwareTransform(prim), useHWTessellation_, lastVType_);

if (vshader->UseHWTransform()) {
LPDIRECT3DVERTEXBUFFER9 vb_ = NULL;
Expand Down Expand Up @@ -491,7 +491,7 @@ void DrawEngineDX9::DoFlush() {
}

ApplyDrawStateLate();
vshader = shaderManager_->ApplyShader(CanUseHardwareTransform(prim), lastVType_);
vshader = shaderManager_->ApplyShader(CanUseHardwareTransform(prim), useHWTessellation_, lastVType_);
IDirect3DVertexDeclaration9 *pHardwareVertexDecl = SetupDecFmtForDraw(vshader, dec_->GetDecVtxFmt(), dec_->VertexType());

if (pHardwareVertexDecl) {
Expand Down Expand Up @@ -552,7 +552,7 @@ void DrawEngineDX9::DoFlush() {
maxIndex, drawBuffer, numTrans, drawIndexed, &params, &result);

ApplyDrawStateLate();
vshader = shaderManager_->ApplyShader(CanUseHardwareTransform(prim), lastVType_);
vshader = shaderManager_->ApplyShader(false, false, lastVType_);

if (result.action == SW_DRAW_PRIMITIVES) {
if (result.setStencil) {
Expand Down
4 changes: 4 additions & 0 deletions GPU/Directx9/DrawEngineDX9.h
Expand Up @@ -140,6 +140,10 @@ class DrawEngineDX9 : public DrawEngineCommon {

void DispatchFlush() override { Flush(); }

protected:
// Not currently supported.
bool UpdateUseHWTessellation(bool enable) override { return false; }

private:
void DoFlush();

Expand Down
1 change: 0 additions & 1 deletion GPU/Directx9/GPU_DX9.cpp
Expand Up @@ -97,7 +97,6 @@ GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx, Draw::DrawContext *draw)

if (g_Config.bHardwareTessellation) {
// Disable hardware tessellation bacause DX9 is still unsupported.
g_Config.bHardwareTessellation = false;
ERROR_LOG(G3D, "Hardware Tessellation is unsupported, falling back to software tessellation");
auto gr = GetI18NCategory("Graphics");
host->NotifyUserMessage(gr->T("Turn off Hardware Tessellation - unsupported"), 2.5f, 0xFF3030FF);
Expand Down
6 changes: 3 additions & 3 deletions GPU/Directx9/ShaderManagerDX9.cpp
Expand Up @@ -546,15 +546,15 @@ void ShaderManagerDX9::DirtyLastShader() { // disables vertex arrays
lastPShader_ = nullptr;
}

VSShader *ShaderManagerDX9::ApplyShader(bool useHWTransform, u32 vertType) {
VSShader *ShaderManagerDX9::ApplyShader(bool useHWTransform, bool useHWTessellation, u32 vertType) {
// Always use software for flat shading to fix the provoking index.
bool tess = gstate_c.bezier || gstate_c.spline;
useHWTransform = useHWTransform && (tess || gstate.getShadeMode() != GE_SHADE_FLAT);

VShaderID VSID;
if (gstate_c.IsDirty(DIRTY_VERTEXSHADER_STATE)) {
gstate_c.Clean(DIRTY_VERTEXSHADER_STATE);
ComputeVertexShaderID(&VSID, vertType, useHWTransform);
ComputeVertexShaderID(&VSID, vertType, useHWTransform, useHWTessellation);
} else {
VSID = lastVSID_;
}
Expand Down Expand Up @@ -595,7 +595,7 @@ VSShader *ShaderManagerDX9::ApplyShader(bool useHWTransform, u32 vertType) {
}
delete vs;

ComputeVertexShaderID(&VSID, vertType, false);
ComputeVertexShaderID(&VSID, vertType, false, false);

// TODO: Look for existing shader with the appropriate ID, use that instead of generating a new one - however, need to make sure
// that that shader ID is not used when computing the linked shader ID below, because then IDs won't match
Expand Down
2 changes: 1 addition & 1 deletion GPU/Directx9/ShaderManagerDX9.h
Expand Up @@ -81,7 +81,7 @@ class ShaderManagerDX9 : public ShaderManagerCommon {
~ShaderManagerDX9();

void ClearCache(bool deleteThem); // TODO: deleteThem currently not respected
VSShader *ApplyShader(bool useHWTransform, u32 vertType);
VSShader *ApplyShader(bool useHWTransform, bool useHWTessellation, u32 vertType);
void DirtyShader();
void DirtyLastShader() override;

Expand Down
11 changes: 10 additions & 1 deletion GPU/GLES/DrawEngineGLES.cpp
Expand Up @@ -318,7 +318,7 @@ void DrawEngineGLES::DoFlush() {
GEPrimitiveType prim = prevPrim_;

VShaderID vsid;
Shader *vshader = shaderManager_->ApplyVertexShader(CanUseHardwareTransform(prim), lastVType_, &vsid);
Shader *vshader = shaderManager_->ApplyVertexShader(CanUseHardwareTransform(prim), useHWTessellation_, lastVType_, &vsid);

GLRBuffer *vertexBuffer = nullptr;
GLRBuffer *indexBuffer = nullptr;
Expand Down Expand Up @@ -654,6 +654,15 @@ bool DrawEngineGLES::IsCodePtrVertexDecoder(const u8 *ptr) const {
return decJitCache_->IsInSpace(ptr);
}

bool DrawEngineGLES::SupportsHWTessellation() const {
bool hasTexelFetch = gl_extensions.GLES3 || (!gl_extensions.IsGLES && gl_extensions.VersionGEThan(3, 3, 0)) || gl_extensions.EXT_gpu_shader4;
return hasTexelFetch && gstate_c.SupportsAll(GPU_SUPPORTS_VERTEX_TEXTURE_FETCH | GPU_SUPPORTS_TEXTURE_FLOAT);
}

bool DrawEngineGLES::UpdateUseHWTessellation(bool enable) {
return enable && SupportsHWTessellation();
}

void TessellationDataTransferGLES::SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Spline::Weight2D &weights) {
bool hasColor = (vertType & GE_VTYPE_COL_MASK) != 0;
bool hasTexCoord = (vertType & GE_VTYPE_TC_MASK) != 0;
Expand Down
5 changes: 5 additions & 0 deletions GPU/GLES/DrawEngineGLES.h
Expand Up @@ -182,6 +182,11 @@ class DrawEngineGLES : public DrawEngineCommon {

void ClearInputLayoutMap();

bool SupportsHWTessellation() const;

protected:
bool UpdateUseHWTessellation(bool enable) override;

private:
void InitDeviceObjects();
void DestroyDeviceObjects();
Expand Down
4 changes: 1 addition & 3 deletions GPU/GLES/GPU_GLES.cpp
Expand Up @@ -108,9 +108,7 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw)

if (g_Config.bHardwareTessellation) {
// Disable hardware tessellation if device is unsupported.
bool hasTexelFetch = gl_extensions.GLES3 || (!gl_extensions.IsGLES && gl_extensions.VersionGEThan(3, 3, 0)) || gl_extensions.EXT_gpu_shader4;
if (!gstate_c.SupportsAll(GPU_SUPPORTS_VERTEX_TEXTURE_FETCH | GPU_SUPPORTS_TEXTURE_FLOAT) || !hasTexelFetch) {
g_Config.bHardwareTessellation = false;
if (!drawEngine_.SupportsHWTessellation()) {
ERROR_LOG(G3D, "Hardware Tessellation is unsupported, falling back to software tessellation");
auto gr = GetI18NCategory("Graphics");
host->NotifyUserMessage(gr->T("Turn off Hardware Tessellation - unsupported"), 2.5f, 0xFF3030FF);
Expand Down
6 changes: 3 additions & 3 deletions GPU/GLES/ShaderManagerGLES.cpp
Expand Up @@ -645,7 +645,7 @@ Shader *ShaderManagerGLES::CompileVertexShader(VShaderID VSID) {
return new Shader(render_, codeBuffer_, desc, GL_VERTEX_SHADER, useHWTransform, attrMask, uniformMask);
}

Shader *ShaderManagerGLES::ApplyVertexShader(bool useHWTransform, u32 vertType, VShaderID *VSID) {
Shader *ShaderManagerGLES::ApplyVertexShader(bool useHWTransform, bool useHWTessellation, u32 vertType, VShaderID *VSID) {
uint64_t dirty = gstate_c.GetDirtyUniforms();
if (dirty) {
if (lastShader_)
Expand All @@ -656,7 +656,7 @@ Shader *ShaderManagerGLES::ApplyVertexShader(bool useHWTransform, u32 vertType,

if (gstate_c.IsDirty(DIRTY_VERTEXSHADER_STATE)) {
gstate_c.Clean(DIRTY_VERTEXSHADER_STATE);
ComputeVertexShaderID(VSID, vertType, useHWTransform);
ComputeVertexShaderID(VSID, vertType, useHWTransform, useHWTessellation);
} else {
*VSID = lastVSID_;
}
Expand Down Expand Up @@ -687,7 +687,7 @@ Shader *ShaderManagerGLES::ApplyVertexShader(bool useHWTransform, u32 vertType,

// Can still work with software transform.
VShaderID vsidTemp;
ComputeVertexShaderID(&vsidTemp, vertType, false);
ComputeVertexShaderID(&vsidTemp, vertType, false, false);
vs = CompileVertexShader(vsidTemp);
}

Expand Down
2 changes: 1 addition & 1 deletion GPU/GLES/ShaderManagerGLES.h
Expand Up @@ -159,7 +159,7 @@ class ShaderManagerGLES : public ShaderManagerCommon {

// This is the old ApplyShader split into two parts, because of annoying information dependencies.
// If you call ApplyVertexShader, you MUST call ApplyFragmentShader soon afterwards.
Shader *ApplyVertexShader(bool useHWTransform, u32 vertType, VShaderID *VSID);
Shader *ApplyVertexShader(bool useHWTransform, bool useHWTessellation, u32 vertType, VShaderID *VSID);
LinkedShader *ApplyFragmentShader(VShaderID VSID, Shader *vs, u32 vertType, bool useBufferedRendering);

void DeviceLost();
Expand Down
3 changes: 3 additions & 0 deletions GPU/Software/TransformUnit.h
Expand Up @@ -149,4 +149,7 @@ class SoftwareDrawEngine : public DrawEngineCommon {
VertexDecoder *FindVertexDecoder(u32 vtype);

TransformUnit transformUnit;

protected:
bool UpdateUseHWTessellation(bool enable) override { return false; }
};
4 changes: 2 additions & 2 deletions GPU/Vulkan/DrawEngineVulkan.cpp
Expand Up @@ -813,7 +813,7 @@ void DrawEngineVulkan::DoFlush() {
ConvertStateToVulkanKey(*framebufferManager_, shaderManager_, prim, pipelineKey_, dynState_);
}

shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, true); // usehwtransform
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, true, useHWTessellation_); // usehwtransform
_dbg_assert_msg_(G3D, vshader->UseHWTransform(), "Bad vshader");

Draw::NativeObject object = framebufferManager_->UseBufferedRendering() ? Draw::NativeObject::FRAMEBUFFER_RENDERPASS : Draw::NativeObject::BACKBUFFER_RENDERPASS;
Expand Down Expand Up @@ -923,7 +923,7 @@ void DrawEngineVulkan::DoFlush() {
sampler = nullSampler_;
}
if (!lastPipeline_ || gstate_c.IsDirty(DIRTY_BLEND_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_RASTER_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE) || prim != lastPrim_) {
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, false); // usehwtransform
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, false, false); // usehwtransform
_dbg_assert_msg_(G3D, !vshader->UseHWTransform(), "Bad vshader");
if (prim != lastPrim_ || gstate_c.IsDirty(DIRTY_BLEND_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_RASTER_STATE | DIRTY_DEPTHSTENCIL_STATE)) {
ConvertStateToVulkanKey(*framebufferManager_, shaderManager_, prim, pipelineKey_, dynState_);
Expand Down
4 changes: 2 additions & 2 deletions GPU/Vulkan/ShaderManagerVulkan.cpp
Expand Up @@ -228,11 +228,11 @@ uint64_t ShaderManagerVulkan::UpdateUniforms(bool useBufferedRendering) {
return dirty;
}

void ShaderManagerVulkan::GetShaders(int prim, u32 vertType, VulkanVertexShader **vshader, VulkanFragmentShader **fshader, bool useHWTransform) {
void ShaderManagerVulkan::GetShaders(int prim, u32 vertType, VulkanVertexShader **vshader, VulkanFragmentShader **fshader, bool useHWTransform, bool useHWTessellation) {
VShaderID VSID;
if (gstate_c.IsDirty(DIRTY_VERTEXSHADER_STATE)) {
gstate_c.Clean(DIRTY_VERTEXSHADER_STATE);
ComputeVertexShaderID(&VSID, vertType, useHWTransform);
ComputeVertexShaderID(&VSID, vertType, useHWTransform, useHWTessellation);
} else {
VSID = lastVSID_;
}
Expand Down
2 changes: 1 addition & 1 deletion GPU/Vulkan/ShaderManagerVulkan.h
Expand Up @@ -88,7 +88,7 @@ class ShaderManagerVulkan : public ShaderManagerCommon {

void DeviceRestore(VulkanContext *vulkan, Draw::DrawContext *draw);

void GetShaders(int prim, u32 vertType, VulkanVertexShader **vshader, VulkanFragmentShader **fshader, bool useHWTransform);
void GetShaders(int prim, u32 vertType, VulkanVertexShader **vshader, VulkanFragmentShader **fshader, bool useHWTransform, bool useHWTessellation);
void ClearShaders();
void DirtyShader();
void DirtyLastShader() override;
Expand Down

0 comments on commit ac60e2e

Please sign in to comment.