Vulkan: Fix Prescale UV
This commit is contained in:
parent
e8758c1ea0
commit
20f227cc4d
4 changed files with 95 additions and 65 deletions
|
@ -121,14 +121,14 @@ TransformDrawEngine::TransformDrawEngine()
|
||||||
: decodedVerts_(0),
|
: decodedVerts_(0),
|
||||||
prevPrim_(GE_PRIM_INVALID),
|
prevPrim_(GE_PRIM_INVALID),
|
||||||
lastVType_(-1),
|
lastVType_(-1),
|
||||||
shaderManager_(0),
|
shaderManager_(nullptr),
|
||||||
textureCache_(0),
|
textureCache_(nullptr),
|
||||||
framebufferManager_(0),
|
framebufferManager_(nullptr),
|
||||||
numDrawCalls(0),
|
numDrawCalls(0),
|
||||||
vertexCountInDrawCalls(0),
|
vertexCountInDrawCalls(0),
|
||||||
decodeCounter_(0),
|
decodeCounter_(0),
|
||||||
dcid_(0),
|
dcid_(0),
|
||||||
uvScale(0),
|
uvScale(nullptr),
|
||||||
fboTexNeedBind_(false),
|
fboTexNeedBind_(false),
|
||||||
fboTexBound_(false) {
|
fboTexBound_(false) {
|
||||||
decimationCounter_ = VERTEXCACHE_DECIMATION_INTERVAL;
|
decimationCounter_ = VERTEXCACHE_DECIMATION_INTERVAL;
|
||||||
|
|
|
@ -71,6 +71,7 @@ DrawEngineVulkan::DrawEngineVulkan(VulkanContext *vulkan)
|
||||||
framebufferManager_(nullptr),
|
framebufferManager_(nullptr),
|
||||||
numDrawCalls(0),
|
numDrawCalls(0),
|
||||||
vertexCountInDrawCalls(0),
|
vertexCountInDrawCalls(0),
|
||||||
|
uvScale(nullptr),
|
||||||
fboTexNeedBind_(false),
|
fboTexNeedBind_(false),
|
||||||
fboTexBound_(false),
|
fboTexBound_(false),
|
||||||
curFrame_(0),
|
curFrame_(0),
|
||||||
|
@ -92,6 +93,10 @@ DrawEngineVulkan::DrawEngineVulkan(VulkanContext *vulkan)
|
||||||
|
|
||||||
indexGen.Setup(decIndex);
|
indexGen.Setup(decIndex);
|
||||||
|
|
||||||
|
if (g_Config.bPrescaleUV) {
|
||||||
|
uvScale = new UVScale[MAX_DEFERRED_DRAW_CALLS];
|
||||||
|
}
|
||||||
|
|
||||||
// All resources we need for PSP drawing. Usually only bindings 0 and 2-4 are populated.
|
// All resources we need for PSP drawing. Usually only bindings 0 and 2-4 are populated.
|
||||||
VkDescriptorSetLayoutBinding bindings[5];
|
VkDescriptorSetLayoutBinding bindings[5];
|
||||||
bindings[0].descriptorCount = 1;
|
bindings[0].descriptorCount = 1;
|
||||||
|
@ -202,6 +207,7 @@ DrawEngineVulkan::~DrawEngineVulkan() {
|
||||||
nullTexture_->Destroy();
|
nullTexture_->Destroy();
|
||||||
delete nullTexture_;
|
delete nullTexture_;
|
||||||
}
|
}
|
||||||
|
delete[] uvScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawEngineVulkan::BeginFrame() {
|
void DrawEngineVulkan::BeginFrame() {
|
||||||
|
@ -312,6 +318,10 @@ void DrawEngineVulkan::SubmitPrim(void *verts, void *inds, GEPrimitiveType prim,
|
||||||
dc.indexUpperBound = vertexCount - 1;
|
dc.indexUpperBound = vertexCount - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (uvScale) {
|
||||||
|
uvScale[numDrawCalls] = gstate_c.uv;
|
||||||
|
}
|
||||||
|
|
||||||
numDrawCalls++;
|
numDrawCalls++;
|
||||||
vertexCountInDrawCalls += vertexCount;
|
vertexCountInDrawCalls += vertexCount;
|
||||||
|
|
||||||
|
@ -324,6 +334,70 @@ void DrawEngineVulkan::SubmitPrim(void *verts, void *inds, GEPrimitiveType prim,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DrawEngineVulkan::DecodeVertsStep(u8 *dest, int &i, int &decodedVerts) {
|
||||||
|
const DeferredDrawCall &dc = drawCalls[i];
|
||||||
|
|
||||||
|
indexGen.SetIndex(decodedVerts);
|
||||||
|
int indexLowerBound = dc.indexLowerBound, indexUpperBound = dc.indexUpperBound;
|
||||||
|
|
||||||
|
void *inds = dc.inds;
|
||||||
|
if (dc.indexType == GE_VTYPE_IDX_NONE >> GE_VTYPE_IDX_SHIFT) {
|
||||||
|
// Decode the verts and apply morphing. Simple.
|
||||||
|
dec_->DecodeVerts(dest + decodedVerts * (int)dec_->GetDecVtxFmt().stride,
|
||||||
|
dc.verts, indexLowerBound, indexUpperBound);
|
||||||
|
decodedVerts += indexUpperBound - indexLowerBound + 1;
|
||||||
|
indexGen.AddPrim(dc.prim, dc.vertexCount);
|
||||||
|
} else {
|
||||||
|
// It's fairly common that games issue long sequences of PRIM calls, with differing
|
||||||
|
// inds pointer but the same base vertex pointer. We'd like to reuse vertices between
|
||||||
|
// these as much as possible, so we make sure here to combine as many as possible
|
||||||
|
// into one nice big drawcall, sharing data.
|
||||||
|
|
||||||
|
// 1. Look ahead to find the max index, only looking as "matching" drawcalls.
|
||||||
|
// Expand the lower and upper bounds as we go.
|
||||||
|
int lastMatch = i;
|
||||||
|
const int total = numDrawCalls;
|
||||||
|
for (int j = i + 1; j < total; ++j) {
|
||||||
|
if (drawCalls[j].verts != dc.verts)
|
||||||
|
break;
|
||||||
|
|
||||||
|
indexLowerBound = std::min(indexLowerBound, (int)drawCalls[j].indexLowerBound);
|
||||||
|
indexUpperBound = std::max(indexUpperBound, (int)drawCalls[j].indexUpperBound);
|
||||||
|
lastMatch = j;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Loop through the drawcalls, translating indices as we go.
|
||||||
|
switch (dc.indexType) {
|
||||||
|
case GE_VTYPE_IDX_8BIT >> GE_VTYPE_IDX_SHIFT:
|
||||||
|
for (int j = i; j <= lastMatch; j++) {
|
||||||
|
indexGen.TranslatePrim(drawCalls[j].prim, drawCalls[j].vertexCount, (const u8 *)drawCalls[j].inds, indexLowerBound);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GE_VTYPE_IDX_16BIT >> GE_VTYPE_IDX_SHIFT:
|
||||||
|
for (int j = i; j <= lastMatch; j++) {
|
||||||
|
indexGen.TranslatePrim(drawCalls[j].prim, drawCalls[j].vertexCount, (const u16 *)drawCalls[j].inds, indexLowerBound);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int vertexCount = indexUpperBound - indexLowerBound + 1;
|
||||||
|
|
||||||
|
// This check is a workaround for Pangya Fantasy Golf, which sends bogus index data when switching items in "My Room" sometimes.
|
||||||
|
if (decodedVerts + vertexCount > VERTEX_BUFFER_MAX) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Decode that range of vertex data.
|
||||||
|
dec_->DecodeVerts(dest + decodedVerts * (int)dec_->GetDecVtxFmt().stride,
|
||||||
|
dc.verts, indexLowerBound, indexUpperBound);
|
||||||
|
decodedVerts += vertexCount;
|
||||||
|
|
||||||
|
// 4. Advance indexgen vertex counter.
|
||||||
|
indexGen.Advance(vertexCount);
|
||||||
|
i = lastMatch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DrawEngineVulkan::DecodeVerts(VulkanPushBuffer *push, uint32_t *bindOffset, VkBuffer *vkbuf) {
|
void DrawEngineVulkan::DecodeVerts(VulkanPushBuffer *push, uint32_t *bindOffset, VkBuffer *vkbuf) {
|
||||||
int decodedVerts = 0;
|
int decodedVerts = 0;
|
||||||
|
|
||||||
|
@ -343,69 +417,19 @@ void DrawEngineVulkan::DecodeVerts(VulkanPushBuffer *push, uint32_t *bindOffset,
|
||||||
dest = (u8 *)push->Push(vertsToDecode * dec_->GetDecVtxFmt().stride, bindOffset, vkbuf);
|
dest = (u8 *)push->Push(vertsToDecode * dec_->GetDecVtxFmt().stride, bindOffset, vkbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < numDrawCalls; i++) {
|
if (uvScale) {
|
||||||
const DeferredDrawCall &dc = drawCalls[i];
|
const UVScale origUV = gstate_c.uv;
|
||||||
|
for (int i = 0; i < numDrawCalls; i++) {
|
||||||
indexGen.SetIndex(decodedVerts);
|
gstate_c.uv = uvScale[i];
|
||||||
int indexLowerBound = dc.indexLowerBound, indexUpperBound = dc.indexUpperBound;
|
DecodeVertsStep(dest, i, decodedVerts); // Note that this can modify i
|
||||||
|
}
|
||||||
void *inds = dc.inds;
|
gstate_c.uv = origUV;
|
||||||
if (dc.indexType == GE_VTYPE_IDX_NONE >> GE_VTYPE_IDX_SHIFT) {
|
} else {
|
||||||
// Decode the verts and apply morphing. Simple.
|
for (int i = 0; i < numDrawCalls; i++) {
|
||||||
dec_->DecodeVerts(dest + decodedVerts * (int)dec_->GetDecVtxFmt().stride,
|
DecodeVertsStep(dest, i, decodedVerts); // Note that this can modify i
|
||||||
dc.verts, indexLowerBound, indexUpperBound);
|
|
||||||
decodedVerts += indexUpperBound - indexLowerBound + 1;
|
|
||||||
indexGen.AddPrim(dc.prim, dc.vertexCount);
|
|
||||||
} else {
|
|
||||||
// It's fairly common that games issue long sequences of PRIM calls, with differing
|
|
||||||
// inds pointer but the same base vertex pointer. We'd like to reuse vertices between
|
|
||||||
// these as much as possible, so we make sure here to combine as many as possible
|
|
||||||
// into one nice big drawcall, sharing data.
|
|
||||||
|
|
||||||
// 1. Look ahead to find the max index, only looking as "matching" drawcalls.
|
|
||||||
// Expand the lower and upper bounds as we go.
|
|
||||||
int lastMatch = i;
|
|
||||||
const int total = numDrawCalls;
|
|
||||||
for (int j = i + 1; j < total; ++j) {
|
|
||||||
if (drawCalls[j].verts != dc.verts)
|
|
||||||
break;
|
|
||||||
|
|
||||||
indexLowerBound = std::min(indexLowerBound, (int)drawCalls[j].indexLowerBound);
|
|
||||||
indexUpperBound = std::max(indexUpperBound, (int)drawCalls[j].indexUpperBound);
|
|
||||||
lastMatch = j;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Loop through the drawcalls, translating indices as we go.
|
|
||||||
switch (dc.indexType) {
|
|
||||||
case GE_VTYPE_IDX_8BIT >> GE_VTYPE_IDX_SHIFT:
|
|
||||||
for (int j = i; j <= lastMatch; j++) {
|
|
||||||
indexGen.TranslatePrim(drawCalls[j].prim, drawCalls[j].vertexCount, (const u8 *)drawCalls[j].inds, indexLowerBound);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case GE_VTYPE_IDX_16BIT >> GE_VTYPE_IDX_SHIFT:
|
|
||||||
for (int j = i; j <= lastMatch; j++) {
|
|
||||||
indexGen.TranslatePrim(drawCalls[j].prim, drawCalls[j].vertexCount, (const u16 *)drawCalls[j].inds, indexLowerBound);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int vertexCount = indexUpperBound - indexLowerBound + 1;
|
|
||||||
|
|
||||||
// This check is a workaround for Pangya Fantasy Golf, which sends bogus index data when switching items in "My Room" sometimes.
|
|
||||||
if (decodedVerts + vertexCount > VERTEX_BUFFER_MAX) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Decode that range of vertex data.
|
|
||||||
dec_->DecodeVerts(dest + decodedVerts * (int)dec_->GetDecVtxFmt().stride,
|
|
||||||
dc.verts, indexLowerBound, indexUpperBound);
|
|
||||||
decodedVerts += vertexCount;
|
|
||||||
|
|
||||||
// 4. Advance indexgen vertex counter.
|
|
||||||
indexGen.Advance(vertexCount);
|
|
||||||
i = lastMatch;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sanity check
|
// Sanity check
|
||||||
if (indexGen.Prim() < 0) {
|
if (indexGen.Prim() < 0) {
|
||||||
ERROR_LOG_REPORT(G3D, "DecodeVerts: Failed to deduce prim: %i", indexGen.Prim());
|
ERROR_LOG_REPORT(G3D, "DecodeVerts: Failed to deduce prim: %i", indexGen.Prim());
|
||||||
|
|
|
@ -147,6 +147,8 @@ private:
|
||||||
struct FrameData;
|
struct FrameData;
|
||||||
|
|
||||||
void DecodeVerts(VulkanPushBuffer *push, uint32_t *bindOffset, VkBuffer *vkbuf);
|
void DecodeVerts(VulkanPushBuffer *push, uint32_t *bindOffset, VkBuffer *vkbuf);
|
||||||
|
void DecodeVertsStep(u8 *dest, int &i, int &decodedVerts);
|
||||||
|
|
||||||
void DoFlush(VkCommandBuffer cmd);
|
void DoFlush(VkCommandBuffer cmd);
|
||||||
void UpdateUBOs(FrameData *frame);
|
void UpdateUBOs(FrameData *frame);
|
||||||
|
|
||||||
|
@ -244,6 +246,7 @@ private:
|
||||||
DeferredDrawCall drawCalls[MAX_DEFERRED_DRAW_CALLS];
|
DeferredDrawCall drawCalls[MAX_DEFERRED_DRAW_CALLS];
|
||||||
int numDrawCalls;
|
int numDrawCalls;
|
||||||
int vertexCountInDrawCalls;
|
int vertexCountInDrawCalls;
|
||||||
|
UVScale *uvScale;
|
||||||
|
|
||||||
bool fboTexNeedBind_;
|
bool fboTexNeedBind_;
|
||||||
bool fboTexBound_;
|
bool fboTexBound_;
|
||||||
|
|
|
@ -311,6 +311,9 @@ void GameSettingsScreen::CreateViews() {
|
||||||
CheckBox *depthWrite = graphicsSettings->Add(new CheckBox(&g_Config.bAlwaysDepthWrite, gr->T("Always Depth Write")));
|
CheckBox *depthWrite = graphicsSettings->Add(new CheckBox(&g_Config.bAlwaysDepthWrite, gr->T("Always Depth Write")));
|
||||||
depthWrite->SetDisabledPtr(&g_Config.bSoftwareRendering);
|
depthWrite->SetDisabledPtr(&g_Config.bSoftwareRendering);
|
||||||
|
|
||||||
|
graphicsSettings->Add(new CheckBox(&g_Config.bPrescaleUV, gr->T("Texture Coord Speedhack")));
|
||||||
|
depthWrite->SetDisabledPtr(&g_Config.bSoftwareRendering);
|
||||||
|
|
||||||
static const char *bloomHackOptions[] = { "Off", "Safe", "Balanced", "Aggressive" };
|
static const char *bloomHackOptions[] = { "Off", "Safe", "Balanced", "Aggressive" };
|
||||||
PopupMultiChoice *bloomHack = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iBloomHack, gr->T("Lower resolution for effects (reduces artifacts)"), bloomHackOptions, 0, ARRAY_SIZE(bloomHackOptions), gr->GetName(), screenManager()));
|
PopupMultiChoice *bloomHack = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iBloomHack, gr->T("Lower resolution for effects (reduces artifacts)"), bloomHackOptions, 0, ARRAY_SIZE(bloomHackOptions), gr->GetName(), screenManager()));
|
||||||
bloomHackEnable_ = !g_Config.bSoftwareRendering && (g_Config.iInternalResolution != 1);
|
bloomHackEnable_ = !g_Config.bSoftwareRendering && (g_Config.iInternalResolution != 1);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue