Merge pull request #10116 from hrydgard/vulkan-pipeline-dedupe

Vulkan: Fix bug where we ended up creating duplicate pipelines even if vertices decoded to the same format, if they were created from different formats.
This commit is contained in:
Henrik Rydgård 2017-11-13 12:23:41 +01:00 committed by GitHub
commit 43ae868562
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 28 additions and 44 deletions

View File

@ -73,13 +73,15 @@ int DecFmtSize(u8 fmt) {
case DEC_U16_2: return 4;
case DEC_U16_3: return 8;
case DEC_U16_4: return 8;
case DEC_U8A_2: return 4;
case DEC_U16A_2: return 4;
default:
return 0;
}
}
void DecVtxFormat::ComputeID() {
id = w0fmt | (w1fmt << 4) | (uvfmt << 8) | (c0fmt << 12) | (c1fmt << 16) | (nrmfmt << 20) | (posfmt << 24);
}
void GetIndexBounds(const void *inds, int count, u32 vertType, u16 *indexLowerBound, u16 *indexUpperBound) {
// Find index bounds. Could cache this in display lists.
// Also, this could be greatly sped up with SSE2/NEON, although rarely a bottleneck.
@ -1152,6 +1154,8 @@ void VertexDecoder::SetVertexType(u32 fmt, const VertexDecoderOptions &options,
decFmt.stride = decOff;
decFmt.ComputeID();
size = align(size, biggest);
onesize_ = size;
size *= morphcount;

View File

@ -43,6 +43,7 @@
// Can write code to easily bind these using OpenGL, or read these manually.
// No morph support, that is taken care of by the VertexDecoder.
// Keep this in 4 bits.
enum {
DEC_NONE,
DEC_FLOAT_1,
@ -59,8 +60,6 @@ enum {
DEC_U16_2,
DEC_U16_3,
DEC_U16_4,
DEC_U8A_2,
DEC_U16A_2,
};
int DecFmtSize(u8 fmt);
@ -74,6 +73,9 @@ struct DecVtxFormat {
u8 nrmfmt; u8 nrmoff;
u8 posfmt; u8 posoff;
short stride;
uint32_t id;
void ComputeID();
};
struct TransformedVertex
@ -297,21 +299,6 @@ public:
}
break;
case DEC_U8A_2:
{
const u8 *b = (const u8 *)(data_ + decFmt_.uvoff);
uv[0] = (float)b[0];
uv[1] = (float)b[1];
}
break;
case DEC_U16A_2:
{
const u16 *p = (const u16 *)(data_ + decFmt_.uvoff);
uv[0] = (float)p[0];
uv[1] = (float)p[1];
}
break;
default:
ERROR_LOG_REPORT_ONCE(fmtuv, G3D, "Reader: Unsupported UV Format %d", decFmt_.uvfmt);
memset(uv, 0, sizeof(float) * 2);

View File

@ -175,8 +175,6 @@ static const DeclTypeInfo VComp[] = {
{ DXGI_FORMAT_UNKNOWN, "UNUSED_DEC_U16_2" }, // DEC_U16_2,
{ DXGI_FORMAT_R16G16B16A16_UNORM ,"D3DDECLTYPE_USHORT4N "}, // DEC_U16_3,
{ DXGI_FORMAT_R16G16B16A16_UNORM ,"D3DDECLTYPE_USHORT4N "}, // DEC_U16_4,
{ DXGI_FORMAT_UNKNOWN, "UNUSED_DEC_U8A_2"}, // DEC_U8A_2,
{ DXGI_FORMAT_UNKNOWN, "UNUSED_DEC_U16A_2" }, // DEC_U16A_2,
};
static void VertexAttribSetup(D3D11_INPUT_ELEMENT_DESC * VertexElement, u8 fmt, u8 offset, const char *semantic, u8 semantic_index = 0) {

View File

@ -155,9 +155,6 @@ static const DeclTypeInfo VComp[] = {
{0, "UNUSED_DEC_U16_2" }, // DEC_U16_2,
{D3DDECLTYPE_USHORT4N ,"D3DDECLTYPE_USHORT4N "}, // DEC_U16_3,
{D3DDECLTYPE_USHORT4N ,"D3DDECLTYPE_USHORT4N "}, // DEC_U16_4,
// Not supported in regular DX9 so faking, will cause graphics bugs until worked around
{0,"UNUSED_DEC_U8A_2"}, // DEC_U8A_2,
{0,"UNUSED_DEC_U16A_2" }, // DEC_U16A_2,
};
static void VertexAttribSetup(D3DVERTEXELEMENT9 * VertexElement, u8 fmt, u8 offset, u8 usage, u8 usage_index = 0) {

View File

@ -228,8 +228,6 @@ static const GlTypeInfo GLComp[] = {
{GL_UNSIGNED_SHORT, 2, GL_TRUE},// DEC_U16_2,
{GL_UNSIGNED_SHORT, 3, GL_TRUE},// DEC_U16_3,
{GL_UNSIGNED_SHORT, 4, GL_TRUE},// DEC_U16_4,
{GL_UNSIGNED_BYTE, 2, GL_FALSE},// DEC_U8A_2,
{GL_UNSIGNED_SHORT, 2, GL_FALSE},// DEC_U16A_2,
};
static inline void VertexAttribSetup(int attrib, int fmt, int stride, u8 *ptr) {

View File

@ -887,7 +887,7 @@ void DrawEngineVulkan::DoFlush() {
}
Draw::NativeObject object = g_Config.iRenderingMode != 0 ? Draw::NativeObject::FRAMEBUFFER_RENDERPASS : Draw::NativeObject::BACKBUFFER_RENDERPASS;
VkRenderPass renderPass = (VkRenderPass)draw_->GetNativeObject(object);
VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(pipelineLayout_, renderPass, pipelineKey_, dec_, vshader, fshader, true);
VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(pipelineLayout_, renderPass, pipelineKey_, &dec_->decFmt, vshader, fshader, true);
if (!pipeline) {
// Already logged, let's bail out.
return;
@ -985,7 +985,7 @@ void DrawEngineVulkan::DoFlush() {
}
Draw::NativeObject object = g_Config.iRenderingMode != 0 ? Draw::NativeObject::FRAMEBUFFER_RENDERPASS : Draw::NativeObject::BACKBUFFER_RENDERPASS;
VkRenderPass renderPass = (VkRenderPass)draw_->GetNativeObject(object);
VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(pipelineLayout_, renderPass, pipelineKey_, dec_, vshader, fshader, false);
VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(pipelineLayout_, renderPass, pipelineKey_, &dec_->decFmt, vshader, fshader, false);
if (!pipeline) {
// Already logged, let's bail out.
return;

View File

@ -66,9 +66,6 @@ static const DeclTypeInfo VComp[] = {
{ VK_FORMAT_R16G16_UNORM, "R16G16_UNORM" }, // DEC_U16_2,
{ VK_FORMAT_R16G16B16A16_UNORM, "R16G16B16A16_UNORM " }, // DEC_U16_3,
{ VK_FORMAT_R16G16B16A16_UNORM, "R16G16B16A16_UNORM " }, // DEC_U16_4,
{ VK_FORMAT_R8G8_UINT, "R8G8_UINT" }, // DEC_U8A_2,
{ VK_FORMAT_R16G16_UINT, "R16G16_UINT" }, // DEC_U16A_2,
};
static void VertexAttribSetup(VkVertexInputAttributeDescription *attr, int fmt, int offset, PspAttributeLocation location) {
@ -121,7 +118,7 @@ static bool UsesBlendConstant(int factor) {
static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pipelineCache,
VkPipelineLayout layout, VkRenderPass renderPass, const VulkanPipelineRasterStateKey &key,
const VertexDecoder *vtxDec, VulkanVertexShader *vs, VulkanFragmentShader *fs, bool useHwTransform, float lineWidth) {
const DecVtxFormat *decFmt, VulkanVertexShader *vs, VulkanFragmentShader *fs, bool useHwTransform, float lineWidth) {
bool useBlendConstant = false;
VkPipelineColorBlendAttachmentState blend0 = {};
@ -229,10 +226,10 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip
VkVertexInputAttributeDescription attrs[8];
int attributeCount;
if (useHwTransform) {
attributeCount = SetupVertexAttribs(attrs, vtxDec->decFmt);
vertexStride = vtxDec->decFmt.stride;
attributeCount = SetupVertexAttribs(attrs, *decFmt);
vertexStride = decFmt->stride;
} else {
attributeCount = SetupVertexAttribsPretransformed(attrs, vtxDec->decFmt);
attributeCount = SetupVertexAttribsPretransformed(attrs, *decFmt);
vertexStride = 36;
}
@ -301,7 +298,7 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip
return vulkanPipeline;
}
VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VkPipelineLayout layout, VkRenderPass renderPass, const VulkanPipelineRasterStateKey &rasterKey, const VertexDecoder *vtxDec, VulkanVertexShader *vs, VulkanFragmentShader *fs, bool useHwTransform) {
VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VkPipelineLayout layout, VkRenderPass renderPass, const VulkanPipelineRasterStateKey &rasterKey, const DecVtxFormat *decFmt, VulkanVertexShader *vs, VulkanFragmentShader *fs, bool useHwTransform) {
VulkanPipelineKey key;
if (!renderPass)
Crash();
@ -311,7 +308,7 @@ VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VkPipelineLayout layo
key.useHWTransform = useHwTransform;
key.vShader = vs->GetModule();
key.fShader = fs->GetModule();
key.vtxDec = useHwTransform ? vtxDec : nullptr;
key.vtxDecId = useHwTransform ? decFmt->id : 0;
auto iter = pipelines_.Get(key);
if (iter)
@ -321,7 +318,7 @@ VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VkPipelineLayout layo
VulkanPipeline *pipeline = CreateVulkanPipeline(
vulkan_->GetDevice(), pipelineCache_, layout, renderPass,
rasterKey, vtxDec, vs, fs, useHwTransform, lineWidth_);
rasterKey, decFmt, vs, fs, useHwTransform, lineWidth_);
// Even if the result is nullptr, insert it so we don't try to create it repeatedly.
pipelines_.Insert(key, pipeline);
return pipeline;

View File

@ -41,7 +41,7 @@ struct VulkanPipelineKey {
VulkanPipelineRasterStateKey raster; // prim is included here
VkRenderPass renderPass;
bool useHWTransform;
const VertexDecoder *vtxDec;
uint32_t vtxDecId;
VkShaderModule vShader;
VkShaderModule fShader;
@ -77,7 +77,7 @@ public:
PipelineManagerVulkan(VulkanContext *ctx);
~PipelineManagerVulkan();
VulkanPipeline *GetOrCreatePipeline(VkPipelineLayout layout, VkRenderPass renderPass, const VulkanPipelineRasterStateKey &rasterKey, const VertexDecoder *vtxDec, VulkanVertexShader *vs, VulkanFragmentShader *fs, bool useHwTransform);
VulkanPipeline *GetOrCreatePipeline(VkPipelineLayout layout, VkRenderPass renderPass, const VulkanPipelineRasterStateKey &rasterKey, const DecVtxFormat *decFmt, VulkanVertexShader *vs, VulkanFragmentShader *fs, bool useHwTransform);
int GetNumPipelines() const { return (int)pipelines_.size(); }
void Clear();

View File

@ -899,14 +899,17 @@ UI::EventReturn JitCompareScreen::OnCurrentBlock(UI::EventParams &e) {
return UI::EVENT_DONE;
}
void ShaderListScreen::ListShaders(DebugShaderType shaderType, UI::LinearLayout *view) {
int ShaderListScreen::ListShaders(DebugShaderType shaderType, UI::LinearLayout *view) {
using namespace UI;
std::vector<std::string> shaderIds_ = gpu->DebugGetShaderIDs(shaderType);
int count = 0;
for (auto id : shaderIds_) {
Choice *choice = view->Add(new Choice(gpu->DebugGetShaderString(id, shaderType, SHADER_STRING_SHORT_DESC)));
choice->SetTag(id);
choice->OnClick.Handle(this, &ShaderListScreen::OnShaderClick);
count++;
}
return count;
}
struct { DebugShaderType type; const char *name; } shaderTypes[] = {
@ -933,9 +936,9 @@ void ShaderListScreen::CreateViews() {
for (size_t i = 0; i < ARRAY_SIZE(shaderTypes); i++) {
ScrollView *scroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(1.0));
LinearLayout *shaderList = new LinearLayout(ORIENT_VERTICAL, new LayoutParams(FILL_PARENT, WRAP_CONTENT));
ListShaders(shaderTypes[i].type, shaderList);
int count = ListShaders(shaderTypes[i].type, shaderList);
scroll->Add(shaderList);
tabs_->AddTab(shaderTypes[i].name, scroll);
tabs_->AddTab(StringFromFormat("%s (%d)", shaderTypes[i].name, count), scroll);
}
}

View File

@ -152,7 +152,7 @@ public:
void CreateViews() override;
private:
void ListShaders(DebugShaderType shaderType, UI::LinearLayout *view);
int ListShaders(DebugShaderType shaderType, UI::LinearLayout *view);
UI::EventReturn OnShaderClick(UI::EventParams &e);