mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-20 17:59:08 +02:00
GPU: Track HW tess at start of frame too.
This also makes it so we don't force the setting off when you change backends, and just ignore it if unsupported.
This commit is contained in:
1 parent
46b9454e73
commit
ac60e2ecd4
21 files changed
+52
-30
No files matched your search
@@ -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() {
|
||||
@@ -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) {
|
||||
@@ -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;
|
||||
|
||||
@@ -104,6 +104,7 @@ public:
|
||||
VertexDecoder *GetVertexDecoder(u32 vtype);
|
||||
|
||||
protected:
|
||||
virtual bool UpdateUseHWTessellation(bool enabled) { return enabled; }
|
||||
virtual void ClearTrackedVertexArrays() {}
|
||||
|
||||
int ComputeNumVertsToDecode() const;
|
||||
@@ -132,6 +133,7 @@ protected:
|
||||
}
|
||||
|
||||
bool useHWTransform_ = false;
|
||||
bool useHWTessellation_ = false;
|
||||
|
||||
// Vertex collector buffers
|
||||
u8 *decoded = nullptr;
|
||||
|
||||
@@ -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;
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -514,7 +514,7 @@ rotateVBO:
|
||||
|
||||
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);
|
||||
@@ -598,7 +598,7 @@ rotateVBO:
|
||||
|
||||
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());
|
||||
|
||||
@@ -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_;
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -491,7 +491,7 @@ rotateVBO:
|
||||
}
|
||||
|
||||
ApplyDrawStateLate();
|
||||
vshader = shaderManager_->ApplyShader(CanUseHardwareTransform(prim), lastVType_);
|
||||
vshader = shaderManager_->ApplyShader(CanUseHardwareTransform(prim), useHWTessellation_, lastVType_);
|
||||
IDirect3DVertexDeclaration9 *pHardwareVertexDecl = SetupDecFmtForDraw(vshader, dec_->GetDecVtxFmt(), dec_->VertexType());
|
||||
|
||||
if (pHardwareVertexDecl) {
|
||||
@@ -552,7 +552,7 @@ rotateVBO:
|
||||
maxIndex, drawBuffer, numTrans, drawIndexed, ¶ms, &result);
|
||||
|
||||
ApplyDrawStateLate();
|
||||
vshader = shaderManager_->ApplyShader(CanUseHardwareTransform(prim), lastVType_);
|
||||
vshader = shaderManager_->ApplyShader(false, false, lastVType_);
|
||||
|
||||
if (result.action == SW_DRAW_PRIMITIVES) {
|
||||
if (result.setStencil) {
|
||||
|
||||
@@ -140,6 +140,10 @@ public:
|
||||
|
||||
void DispatchFlush() override { Flush(); }
|
||||
|
||||
protected:
|
||||
// Not currently supported.
|
||||
bool UpdateUseHWTessellation(bool enable) override { return false; }
|
||||
|
||||
private:
|
||||
void DoFlush();
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -546,7 +546,7 @@ 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);
|
||||
@@ -554,7 +554,7 @@ VSShader *ShaderManagerDX9::ApplyShader(bool useHWTransform, u32 vertType) {
|
||||
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_;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -81,7 +81,7 @@ public:
|
||||
~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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
@@ -182,6 +182,11 @@ public:
|
||||
|
||||
void ClearInputLayoutMap();
|
||||
|
||||
bool SupportsHWTessellation() const;
|
||||
|
||||
protected:
|
||||
bool UpdateUseHWTessellation(bool enable) override;
|
||||
|
||||
private:
|
||||
void InitDeviceObjects();
|
||||
void DestroyDeviceObjects();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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_)
|
||||
@@ -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_;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@ public:
|
||||
|
||||
// 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();
|
||||
|
||||
@@ -149,4 +149,7 @@ public:
|
||||
VertexDecoder *FindVertexDecoder(u32 vtype);
|
||||
|
||||
TransformUnit transformUnit;
|
||||
|
||||
protected:
|
||||
bool UpdateUseHWTessellation(bool enable) override { return false; }
|
||||
};
|
||||
@@ -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;
|
||||
@@ -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_);
|
||||
|
||||
@@ -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_;
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ public:
|
||||
|
||||
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;
|
||||
|
||||
Reference in new issue
Block a user