Merge pull request #16291 from hrydgard/frame-desc-set

Vulkan: Reserve descriptor set 0 for frame-global data, move everything else to set 1
This commit is contained in:
Henrik Rydgård 2022-10-28 18:02:27 +02:00 committed by GitHub
commit ac818d9639
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 147 additions and 63 deletions

View File

@ -98,7 +98,7 @@ R"(#version 450
)"; )";
static const char *vulkanUboDecl = R"( static const char *vulkanUboDecl = R"(
layout (std140, set = 0, binding = 0) uniform Data { layout (std140, set = 1, binding = 0) uniform Data {
vec2 u_texelDelta; vec2 u_texelDelta;
vec2 u_pixelDelta; vec2 u_pixelDelta;
vec4 u_time; vec4 u_time;
@ -187,11 +187,11 @@ bool ConvertToVulkanGLSL(std::string *dest, TranslatedShaderMetadata *destMetada
continue; continue;
} else if (line.find("uniform sampler2D") == 0) { } else if (line.find("uniform sampler2D") == 0) {
if (sscanf(line.c_str(), "uniform sampler2D sampler%d", &num) == 1) if (sscanf(line.c_str(), "uniform sampler2D sampler%d", &num) == 1)
line = StringFromFormat("layout(set = 0, binding = %d) ", num + 1) + line; line = StringFromFormat("layout(set = 1, binding = %d) ", num + 1) + line;
else if (line.find("sampler0") != line.npos) else if (line.find("sampler0") != line.npos)
line = "layout(set = 0, binding = 1) " + line; line = "layout(set = 1, binding = 1) " + line;
else else
line = "layout(set = 0, binding = 2) " + line; line = "layout(set = 1, binding = 2) " + line;
} else if (line.find("uniform ") != std::string::npos) { } else if (line.find("uniform ") != std::string::npos) {
continue; continue;
} else if (2 == sscanf(line.c_str(), "varying vec%d v_texcoord%d;", &vecSize, &num)) { } else if (2 == sscanf(line.c_str(), "varying vec%d v_texcoord%d;", &vecSize, &num)) {

View File

@ -326,7 +326,7 @@ void ShaderWriter::BeginFSMain(Slice<UniformDef> uniforms, Slice<VaryingDef> var
} }
C("layout(location = 0, index = 0) out vec4 fragColor0;\n"); C("layout(location = 0, index = 0) out vec4 fragColor0;\n");
if (!uniforms.is_empty()) { if (!uniforms.is_empty()) {
C("layout(std140, set = 0, binding = 0) uniform bufferVals {\n"); C("layout(std140, set = 1, binding = 0) uniform bufferVals {\n");
for (auto &uniform : uniforms) { for (auto &uniform : uniforms) {
F("%s %s;\n", uniform.type, uniform.name); F("%s %s;\n", uniform.type, uniform.name);
} }
@ -480,9 +480,9 @@ void ShaderWriter::DeclareTexture2D(const SamplerDef &def) {
case GLSL_VULKAN: case GLSL_VULKAN:
// texBindingBase_ is used for the thin3d descriptor set layout, where they start at 1. // texBindingBase_ is used for the thin3d descriptor set layout, where they start at 1.
if (def.flags & SamplerFlags::ARRAY_ON_VULKAN) { if (def.flags & SamplerFlags::ARRAY_ON_VULKAN) {
F("layout(set = 0, binding = %d) uniform sampler2DArray %s;\n", def.binding + texBindingBase_, def.name); F("layout(set = 1, binding = %d) uniform sampler2DArray %s;\n", def.binding + texBindingBase_, def.name);
} else { } else {
F("layout(set = 0, binding = %d) uniform sampler2D %s;\n", def.binding + texBindingBase_, def.name); F("layout(set = 1, binding = %d) uniform sampler2D %s;\n", def.binding + texBindingBase_, def.name);
} }
break; break;
default: default:

View File

@ -1567,7 +1567,7 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c
case VKRRenderCommand::DRAW_INDEXED: case VKRRenderCommand::DRAW_INDEXED:
{ {
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &c.drawIndexed.ds, c.drawIndexed.numUboOffsets, c.drawIndexed.uboOffsets); vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 1, 1, &c.drawIndexed.ds, c.drawIndexed.numUboOffsets, c.drawIndexed.uboOffsets);
vkCmdBindIndexBuffer(cmd, c.drawIndexed.ibuffer, c.drawIndexed.ioffset, (VkIndexType)c.drawIndexed.indexType); vkCmdBindIndexBuffer(cmd, c.drawIndexed.ibuffer, c.drawIndexed.ioffset, (VkIndexType)c.drawIndexed.indexType);
VkDeviceSize voffset = c.drawIndexed.voffset; VkDeviceSize voffset = c.drawIndexed.voffset;
vkCmdBindVertexBuffers(cmd, 0, 1, &c.drawIndexed.vbuffer, &voffset); vkCmdBindVertexBuffers(cmd, 0, 1, &c.drawIndexed.vbuffer, &voffset);
@ -1576,7 +1576,7 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c
} }
case VKRRenderCommand::DRAW: case VKRRenderCommand::DRAW:
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &c.draw.ds, c.draw.numUboOffsets, c.draw.uboOffsets); vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 1, 1, &c.draw.ds, c.draw.numUboOffsets, c.draw.uboOffsets);
if (c.draw.vbuffer) { if (c.draw.vbuffer) {
vkCmdBindVertexBuffers(cmd, 0, 1, &c.draw.vbuffer, &c.draw.voffset); vkCmdBindVertexBuffers(cmd, 0, 1, &c.draw.vbuffer, &c.draw.voffset);
} }
@ -1625,6 +1625,10 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c
} }
break; break;
case VKRRenderCommand::BIND_DESCRIPTOR_SET:
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, c.bindDescSet.pipelineLayout, c.bindDescSet.setNumber, 1, &c.bindDescSet.set, 0, nullptr);
break;
default: default:
ERROR_LOG(G3D, "Unimpl queue command"); ERROR_LOG(G3D, "Unimpl queue command");
break; break;

View File

@ -39,6 +39,7 @@ enum class VKRRenderCommand : uint8_t {
PUSH_CONSTANTS, PUSH_CONSTANTS,
SELF_DEPENDENCY_BARRIER, SELF_DEPENDENCY_BARRIER,
DEBUG_ANNOTATION, DEBUG_ANNOTATION,
BIND_DESCRIPTOR_SET,
NUM_RENDER_COMMANDS, NUM_RENDER_COMMANDS,
}; };
@ -152,6 +153,11 @@ struct VkRenderData {
struct { struct {
const char *annotation; const char *annotation;
} debugAnnotation; } debugAnnotation;
struct {
int setNumber;
VkDescriptorSet set;
VkPipelineLayout pipelineLayout;
} bindDescSet;
}; };
}; };

View File

@ -270,6 +270,16 @@ public:
compileMutex_.unlock(); compileMutex_.unlock();
} }
// Mainly used to bind the frame-global desc set.
// Can be done before binding a pipeline, so not asserting on that.
void BindDescriptorSet(int setNumber, VkDescriptorSet set, VkPipelineLayout pipelineLayout) {
VkRenderData data{ VKRRenderCommand::BIND_DESCRIPTOR_SET };
data.bindDescSet.setNumber = setNumber;
data.bindDescSet.set = set;
data.bindDescSet.pipelineLayout = pipelineLayout;
curRenderStep_->commands.push_back(data);
}
void BindPipeline(VKRGraphicsPipeline *pipeline, PipelineFlags flags, VkPipelineLayout pipelineLayout) { void BindPipeline(VKRGraphicsPipeline *pipeline, PipelineFlags flags, VkPipelineLayout pipelineLayout) {
_dbg_assert_(curRenderStep_ && curRenderStep_->stepType == VKRStepType::RENDER); _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == VKRStepType::RENDER);
_dbg_assert_(pipeline != nullptr); _dbg_assert_(pipeline != nullptr);

View File

@ -35,15 +35,22 @@
#include "Core/Config.h" #include "Core/Config.h"
// We use a simple descriptor set for all rendering: 1 sampler, 1 texture, 1 UBO binding point.
// binding 0 - uniform data
// binding 1 - sampler
// binding 2 - sampler
//
// Vertex data lives in a separate namespace (location = 0, 1, etc)
#include "Common/GPU/Vulkan/VulkanLoader.h" #include "Common/GPU/Vulkan/VulkanLoader.h"
// We support a frame-global descriptor set, which can be optionally used by other code,
// but is not directly used by thin3d. It has to be defined here though, be in set 0
// and specified in every pipeline layout, otherwise it can't sit undisturbed when other
// descriptor sets are bound on top.
// For descriptor set 1, we use a simple descriptor set for all thin3d rendering: 1 UBO binding point, 3 combined texture/samples.
//
// binding 0 - uniform buffer
// binding 1 - texture/sampler
// binding 2 - texture/sampler
// binding 3 - texture/sampler
//
// Vertex data lives in a separate namespace (location = 0, 1, etc).
using namespace PPSSPP_VK; using namespace PPSSPP_VK;
namespace Draw { namespace Draw {
@ -514,6 +521,7 @@ private:
int curIBufferOffset_ = 0; int curIBufferOffset_ = 0;
VkDescriptorSetLayout descriptorSetLayout_ = VK_NULL_HANDLE; VkDescriptorSetLayout descriptorSetLayout_ = VK_NULL_HANDLE;
VkDescriptorSetLayout frameDescSetLayout_ = VK_NULL_HANDLE;
VkPipelineLayout pipelineLayout_ = VK_NULL_HANDLE; VkPipelineLayout pipelineLayout_ = VK_NULL_HANDLE;
VkPipelineCache pipelineCache_ = VK_NULL_HANDLE; VkPipelineCache pipelineCache_ = VK_NULL_HANDLE;
AutoRef<VKFramebuffer> curFramebuffer_; AutoRef<VKFramebuffer> curFramebuffer_;
@ -921,13 +929,25 @@ VKContext::VKContext(VulkanContext *vulkan)
VkResult res = vkCreateDescriptorSetLayout(device_, &dsl, nullptr, &descriptorSetLayout_); VkResult res = vkCreateDescriptorSetLayout(device_, &dsl, nullptr, &descriptorSetLayout_);
_assert_(VK_SUCCESS == res); _assert_(VK_SUCCESS == res);
VkDescriptorSetLayoutBinding frameBindings[1]{};
frameBindings[0].descriptorCount = 1;
frameBindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
frameBindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
frameBindings[0].binding = 0;
dsl.bindingCount = ARRAY_SIZE(frameBindings);
dsl.pBindings = frameBindings;
res = vkCreateDescriptorSetLayout(device_, &dsl, nullptr, &frameDescSetLayout_);
_dbg_assert_(VK_SUCCESS == res);
vulkan_->SetDebugName(descriptorSetLayout_, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, "thin3d_d_layout"); vulkan_->SetDebugName(descriptorSetLayout_, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, "thin3d_d_layout");
VkPipelineLayoutCreateInfo pl = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO }; VkPipelineLayoutCreateInfo pl = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
pl.pPushConstantRanges = nullptr; pl.pPushConstantRanges = nullptr;
pl.pushConstantRangeCount = 0; pl.pushConstantRangeCount = 0;
pl.setLayoutCount = 1; VkDescriptorSetLayout setLayouts[2] = { frameDescSetLayout_, descriptorSetLayout_ };
pl.pSetLayouts = &descriptorSetLayout_; pl.setLayoutCount = ARRAY_SIZE(setLayouts);
pl.pSetLayouts = setLayouts;
res = vkCreatePipelineLayout(device_, &pl, nullptr, &pipelineLayout_); res = vkCreatePipelineLayout(device_, &pl, nullptr, &pipelineLayout_);
_assert_(VK_SUCCESS == res); _assert_(VK_SUCCESS == res);
@ -947,6 +967,7 @@ VKContext::~VKContext() {
delete frame_[i].pushBuffer; delete frame_[i].pushBuffer;
} }
vulkan_->Delete().QueueDeleteDescriptorSetLayout(descriptorSetLayout_); vulkan_->Delete().QueueDeleteDescriptorSetLayout(descriptorSetLayout_);
vulkan_->Delete().QueueDeleteDescriptorSetLayout(frameDescSetLayout_);
vulkan_->Delete().QueueDeletePipelineLayout(pipelineLayout_); vulkan_->Delete().QueueDeletePipelineLayout(pipelineLayout_);
vulkan_->Delete().QueueDeletePipelineCache(pipelineCache_); vulkan_->Delete().QueueDeletePipelineCache(pipelineCache_);
} }
@ -1681,6 +1702,11 @@ uint64_t VKContext::GetNativeObject(NativeObject obj, void *srcObject) {
_dbg_assert_(layer < curFramebuffer_->Layers()); _dbg_assert_(layer < curFramebuffer_->Layers());
return (uint64_t)curFramebuffer_->GetFB()->color.texLayerViews[layer]; return (uint64_t)curFramebuffer_->GetFB()->color.texLayerViews[layer];
} }
case NativeObject::FRAME_DATA_DESC_SET_LAYOUT:
return (uint64_t)frameDescSetLayout_;
case NativeObject::THIN3D_PIPELINE_LAYOUT:
return (uint64_t)pipelineLayout_;
default: default:
Crash(); Crash();
return 0; return 0;

View File

@ -137,7 +137,7 @@ static const std::vector<ShaderSource> fsTexCol = {
"layout(location = 0) in vec4 oColor0;\n" "layout(location = 0) in vec4 oColor0;\n"
"layout(location = 1) in vec2 oTexCoord0;\n" "layout(location = 1) in vec2 oTexCoord0;\n"
"layout(location = 0) out vec4 fragColor0;\n" "layout(location = 0) out vec4 fragColor0;\n"
"layout(set = 0, binding = 1) uniform sampler2D Sampler0;\n" "layout(set = 1, binding = 1) uniform sampler2D Sampler0;\n"
"void main() { fragColor0 = texture(Sampler0, oTexCoord0) * oColor0; }\n" "void main() { fragColor0 = texture(Sampler0, oTexCoord0) * oColor0; }\n"
} }
}; };
@ -181,7 +181,7 @@ static const std::vector<ShaderSource> fsTexColRBSwizzle = {
"layout(location = 0) in vec4 oColor0;\n" "layout(location = 0) in vec4 oColor0;\n"
"layout(location = 1) in vec2 oTexCoord0;\n" "layout(location = 1) in vec2 oTexCoord0;\n"
"layout(location = 0) out vec4 fragColor0\n;" "layout(location = 0) out vec4 fragColor0\n;"
"layout(set = 0, binding = 1) uniform sampler2D Sampler0;\n" "layout(set = 1, binding = 1) uniform sampler2D Sampler0;\n"
"void main() { fragColor0 = texture(Sampler0, oTexCoord0).bgra * oColor0; }\n" "void main() { fragColor0 = texture(Sampler0, oTexCoord0).bgra * oColor0; }\n"
} }
}; };
@ -270,7 +270,7 @@ static const std::vector<ShaderSource> vsCol = {
R"(#version 450 R"(#version 450
#extension GL_ARB_separate_shader_objects : enable #extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable #extension GL_ARB_shading_language_420pack : enable
layout (std140, set = 0, binding = 0) uniform bufferVals { layout (std140, set = 1, binding = 0) uniform bufferVals {
mat4 WorldViewProj; mat4 WorldViewProj;
vec2 TintSaturation; vec2 TintSaturation;
} myBufferVals; } myBufferVals;
@ -416,7 +416,7 @@ VS_OUTPUT main(VS_INPUT input) {
R"(#version 450 R"(#version 450
#extension GL_ARB_separate_shader_objects : enable #extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable #extension GL_ARB_shading_language_420pack : enable
layout (std140, set = 0, binding = 0) uniform bufferVals { layout (std140, set = 1, binding = 0) uniform bufferVals {
mat4 WorldViewProj; mat4 WorldViewProj;
vec2 TintSaturation; vec2 TintSaturation;
} myBufferVals; } myBufferVals;

View File

@ -249,6 +249,8 @@ enum class NativeObject {
RENDER_MANAGER, RENDER_MANAGER,
TEXTURE_VIEW, TEXTURE_VIEW,
NULL_IMAGEVIEW, NULL_IMAGEVIEW,
FRAME_DATA_DESC_SET_LAYOUT,
THIN3D_PIPELINE_LAYOUT,
}; };
enum FBChannel { enum FBChannel {

View File

@ -185,23 +185,23 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
WRITE(p, "layout (depth_unchanged) out float gl_FragDepth;\n"); WRITE(p, "layout (depth_unchanged) out float gl_FragDepth;\n");
} }
WRITE(p, "layout (std140, set = 0, binding = 3) uniform baseUBO {\n%s};\n", ub_baseStr); WRITE(p, "layout (std140, set = 1, binding = 3) uniform baseUBO {\n%s};\n", ub_baseStr);
if (doTexture) { if (doTexture) {
WRITE(p, "layout (binding = 0) uniform %s%s tex;\n", texture3D ? "sampler3D" : "sampler2D", arrayTexture ? "Array" : ""); WRITE(p, "layout (set = 1, binding = 0) uniform %s%s tex;\n", texture3D ? "sampler3D" : "sampler2D", arrayTexture ? "Array" : "");
} }
if (readFramebufferTex) { if (readFramebufferTex) {
// The framebuffer texture is always bound as an array. // The framebuffer texture is always bound as an array.
p.C("layout (binding = 1) uniform sampler2DArray fbotex;\n"); p.C("layout (set = 1, binding = 1) uniform sampler2DArray fbotex;\n");
} else if (fetchFramebuffer) { } else if (fetchFramebuffer) {
p.C("layout (input_attachment_index = 0, binding = 9) uniform subpassInput inputColor;\n"); p.C("layout (input_attachment_index = 0, set = 1, binding = 9) uniform subpassInput inputColor;\n");
if (fragmentShaderFlags) { if (fragmentShaderFlags) {
*fragmentShaderFlags |= FragmentShaderFlags::INPUT_ATTACHMENT; *fragmentShaderFlags |= FragmentShaderFlags::INPUT_ATTACHMENT;
} }
} }
if (shaderDepalMode != ShaderDepalMode::OFF) { if (shaderDepalMode != ShaderDepalMode::OFF) {
WRITE(p, "layout (binding = 2) uniform sampler2D pal;\n"); WRITE(p, "layout (set = 1, binding = 2) uniform sampler2D pal;\n");
} }
// Note: the precision qualifiers must match the vertex shader! // Note: the precision qualifiers must match the vertex shader!

View File

@ -233,14 +233,13 @@ bool PresentationCommon::UpdatePostShader() {
if (gstate_c.Use(GPU_USE_SIMPLE_STEREO_PERSPECTIVE)) { if (gstate_c.Use(GPU_USE_SIMPLE_STEREO_PERSPECTIVE)) {
const ShaderInfo *stereoShaderInfo = GetPostShaderInfo(g_Config.sStereoToMonoShader); const ShaderInfo *stereoShaderInfo = GetPostShaderInfo(g_Config.sStereoToMonoShader);
bool result = CompilePostShader(stereoShaderInfo, &stereoPipeline_); if (stereoShaderInfo) {
if (!result) { bool result = CompilePostShader(stereoShaderInfo, &stereoPipeline_);
// We won't have a stereo shader. We have to check for this later. if (result) {
delete stereoShaderInfo_; stereoShaderInfo_ = new ShaderInfo(*stereoShaderInfo);
stereoShaderInfo_ = nullptr; }
stereoPipeline_ = nullptr;
} else { } else {
stereoShaderInfo_ = new ShaderInfo(*stereoShaderInfo); WARN_LOG(G3D, "Failed to get info about stereo shader '%s'", g_Config.sStereoToMonoShader.c_str());
} }
} }
@ -296,6 +295,8 @@ bool PresentationCommon::UpdatePostShader() {
} }
bool PresentationCommon::CompilePostShader(const ShaderInfo *shaderInfo, Draw::Pipeline **outPipeline) const { bool PresentationCommon::CompilePostShader(const ShaderInfo *shaderInfo, Draw::Pipeline **outPipeline) const {
_assert_(shaderInfo);
std::string vsSourceGLSL = ReadShaderSrc(shaderInfo->vertexShaderFile); std::string vsSourceGLSL = ReadShaderSrc(shaderInfo->vertexShaderFile);
std::string fsSourceGLSL = ReadShaderSrc(shaderInfo->fragmentShaderFile); std::string fsSourceGLSL = ReadShaderSrc(shaderInfo->fragmentShaderFile);
if (vsSourceGLSL.empty() || fsSourceGLSL.empty()) { if (vsSourceGLSL.empty() || fsSourceGLSL.empty()) {

View File

@ -133,12 +133,12 @@ R"( mat3x4 u_bone0; mat3x4 u_bone1; mat3x4 u_bone2; mat3x4 u_bone3; mat3x4 u_bon
static const char * const ub_frame_globalstr = static const char * const ub_frame_globalstr =
R"( vec4 unused; R"( vec4 stereoParams;
)"; )";
// VR stuff will go here. // Frame-global uniforms.
struct UB_FrameGlobal { struct UB_FrameGlobal {
float unused[4]; float stereoParams[4];
}; };
void CalcCullRange(float minValues[4], float maxValues[4], bool flipViewport, bool hasNegZ); void CalcCullRange(float minValues[4], float maxValues[4], bool flipViewport, bool hasNegZ);

View File

@ -249,11 +249,11 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag
if (compat.shaderLanguage == GLSL_VULKAN) { if (compat.shaderLanguage == GLSL_VULKAN) {
WRITE(p, "\n"); WRITE(p, "\n");
WRITE(p, "layout (std140, set = 0, binding = 3) uniform baseVars {\n%s};\n", ub_baseStr); WRITE(p, "layout (std140, set = 1, binding = 3) uniform baseVars {\n%s};\n", ub_baseStr);
if (enableLighting || doShadeMapping) if (enableLighting || doShadeMapping)
WRITE(p, "layout (std140, set = 0, binding = 4) uniform lightVars {\n%s};\n", ub_vs_lightsStr); WRITE(p, "layout (std140, set = 1, binding = 4) uniform lightVars {\n%s};\n", ub_vs_lightsStr);
if (enableBones) if (enableBones)
WRITE(p, "layout (std140, set = 0, binding = 5) uniform boneVars {\n%s};\n", ub_vs_bonesStr); WRITE(p, "layout (std140, set = 1, binding = 5) uniform boneVars {\n%s};\n", ub_vs_bonesStr);
if (enableBones) { if (enableBones) {
WRITE(p, "%s", boneWeightDecl[numBoneWeights]); WRITE(p, "%s", boneWeightDecl[numBoneWeights]);
@ -631,7 +631,7 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag
WRITE(p, " vec4 tex;\n"); WRITE(p, " vec4 tex;\n");
WRITE(p, " vec4 col;\n"); WRITE(p, " vec4 col;\n");
WRITE(p, "};\n"); WRITE(p, "};\n");
WRITE(p, "layout (std430, set = 0, binding = 6) readonly buffer s_tess_data {\n"); WRITE(p, "layout (std430, set = 1, binding = 6) readonly buffer s_tess_data {\n");
WRITE(p, " TessData tess_data[];\n"); WRITE(p, " TessData tess_data[];\n");
WRITE(p, "};\n"); WRITE(p, "};\n");
@ -639,10 +639,10 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag
WRITE(p, " vec4 basis;\n"); WRITE(p, " vec4 basis;\n");
WRITE(p, " vec4 deriv;\n"); WRITE(p, " vec4 deriv;\n");
WRITE(p, "};\n"); WRITE(p, "};\n");
WRITE(p, "layout (std430, set = 0, binding = 7) readonly buffer s_tess_weights_u {\n"); WRITE(p, "layout (std430, set = 1, binding = 7) readonly buffer s_tess_weights_u {\n");
WRITE(p, " TessWeight tess_weights_u[];\n"); WRITE(p, " TessWeight tess_weights_u[];\n");
WRITE(p, "};\n"); WRITE(p, "};\n");
WRITE(p, "layout (std430, set = 0, binding = 8) readonly buffer s_tess_weights_v {\n"); WRITE(p, "layout (std430, set = 1, binding = 8) readonly buffer s_tess_weights_v {\n");
WRITE(p, " TessWeight tess_weights_v[];\n"); WRITE(p, " TessWeight tess_weights_v[];\n");
WRITE(p, "};\n"); WRITE(p, "};\n");
} else if (ShaderLanguageIsOpenGL(compat.shaderLanguage)) { } else if (ShaderLanguageIsOpenGL(compat.shaderLanguage)) {

View File

@ -154,7 +154,7 @@ void DrawEngineVulkan::InitDeviceObjects() {
static constexpr int DEFAULT_DESC_POOL_SIZE = 512; static constexpr int DEFAULT_DESC_POOL_SIZE = 512;
std::vector<VkDescriptorPoolSize> dpTypes; std::vector<VkDescriptorPoolSize> dpTypes;
dpTypes.resize(4); dpTypes.resize(5);
dpTypes[0].descriptorCount = DEFAULT_DESC_POOL_SIZE * 3; dpTypes[0].descriptorCount = DEFAULT_DESC_POOL_SIZE * 3;
dpTypes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; dpTypes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
dpTypes[1].descriptorCount = DEFAULT_DESC_POOL_SIZE * 3; // Don't use these for tess anymore, need max three per set. dpTypes[1].descriptorCount = DEFAULT_DESC_POOL_SIZE * 3; // Don't use these for tess anymore, need max three per set.
@ -163,6 +163,8 @@ void DrawEngineVulkan::InitDeviceObjects() {
dpTypes[2].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; dpTypes[2].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
dpTypes[3].descriptorCount = DEFAULT_DESC_POOL_SIZE; // TODO: Use a separate layout when no spline stuff is needed to reduce the need for these. dpTypes[3].descriptorCount = DEFAULT_DESC_POOL_SIZE; // TODO: Use a separate layout when no spline stuff is needed to reduce the need for these.
dpTypes[3].type = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; dpTypes[3].type = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
dpTypes[4].descriptorCount = 1; // For the frame global uniform buffer.
dpTypes[4].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
VkDescriptorPoolCreateInfo dp{ VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO }; VkDescriptorPoolCreateInfo dp{ VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };
// Don't want to mess around with individually freeing these. // Don't want to mess around with individually freeing these.
@ -185,10 +187,12 @@ void DrawEngineVulkan::InitDeviceObjects() {
VkPipelineLayoutCreateInfo pl{ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO }; VkPipelineLayoutCreateInfo pl{ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
pl.pPushConstantRanges = nullptr; pl.pPushConstantRanges = nullptr;
pl.pushConstantRangeCount = 0; pl.pushConstantRangeCount = 0;
VkDescriptorSetLayout layouts[1] = { descriptorSetLayout_ }; VkDescriptorSetLayout frameDescSetLayout = (VkDescriptorSetLayout)draw_->GetNativeObject(Draw::NativeObject::FRAME_DATA_DESC_SET_LAYOUT);
VkDescriptorSetLayout layouts[2] = { frameDescSetLayout, descriptorSetLayout_};
pl.setLayoutCount = ARRAY_SIZE(layouts); pl.setLayoutCount = ARRAY_SIZE(layouts);
pl.pSetLayouts = layouts; pl.pSetLayouts = layouts;
pl.flags = 0; pl.flags = 0;
res = vkCreatePipelineLayout(device, &pl, nullptr, &pipelineLayout_); res = vkCreatePipelineLayout(device, &pl, nullptr, &pipelineLayout_);
_dbg_assert_(VK_SUCCESS == res); _dbg_assert_(VK_SUCCESS == res);
@ -310,7 +314,8 @@ void DrawEngineVulkan::BeginFrame() {
frame->pushVertex->Begin(vulkan); frame->pushVertex->Begin(vulkan);
frame->pushIndex->Begin(vulkan); frame->pushIndex->Begin(vulkan);
// TODO: How can we make this nicer... frame->frameDescSetUpdated = false;
tessDataTransferVulkan->SetPushBuffer(frame->pushUBO); tessDataTransferVulkan->SetPushBuffer(frame->pushUBO);
DirtyAllUBOs(); DirtyAllUBOs();
@ -1014,6 +1019,30 @@ void DrawEngineVulkan::DoFlush() {
} }
void DrawEngineVulkan::UpdateUBOs(FrameData *frame) { void DrawEngineVulkan::UpdateUBOs(FrameData *frame) {
if (!frame->frameDescSetUpdated) {
// Push frame global constants.
UB_FrameGlobal frameConstants{};
VkDescriptorBufferInfo frameConstantsBufInfo;
frame->pushUBO->PushUBOData(frameConstants, &frameConstantsBufInfo);
VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT);
VulkanRenderManager *renderManager = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
VkDescriptorSetLayout frameDescSetLayout = (VkDescriptorSetLayout)draw_->GetNativeObject(Draw::NativeObject::FRAME_DATA_DESC_SET_LAYOUT);
VkDescriptorSet frameDescSet = frame->descPool.Allocate(1, &frameDescSetLayout, "frame_desc_set");
VkWriteDescriptorSet descWrite{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
descWrite.descriptorCount = 1;
descWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descWrite.dstBinding = 0;
descWrite.dstSet = frameDescSet;
descWrite.pBufferInfo = &frameConstantsBufInfo;
vkUpdateDescriptorSets(vulkan->GetDevice(), 1, &descWrite, 0, nullptr);
renderManager->BindDescriptorSet(0, frameDescSet, pipelineLayout_);
frame->frameDescSetUpdated = true;
}
if ((dirtyUniforms_ & DIRTY_BASE_UNIFORMS) || baseBuf == VK_NULL_HANDLE) { if ((dirtyUniforms_ & DIRTY_BASE_UNIFORMS) || baseBuf == VK_NULL_HANDLE) {
baseUBOOffset = shaderManager_->PushBaseBuffer(frame->pushUBO, &baseBuf); baseUBOOffset = shaderManager_->PushBaseBuffer(frame->pushUBO, &baseBuf);
dirtyUniforms_ &= ~DIRTY_BASE_UNIFORMS; dirtyUniforms_ &= ~DIRTY_BASE_UNIFORMS;

View File

@ -211,7 +211,8 @@ private:
Draw::DrawContext *draw_; Draw::DrawContext *draw_;
// We use a shared descriptor set layout for all PSP draws. // We use a shared descriptor set layouts for all PSP draws.
// Descriptors created from descriptorSetLayout_ is rebound all the time at set 1.
VkDescriptorSetLayout descriptorSetLayout_; VkDescriptorSetLayout descriptorSetLayout_;
VkPipelineLayout pipelineLayout_; VkPipelineLayout pipelineLayout_;
@ -254,6 +255,8 @@ private:
VulkanPushBuffer *pushVertex = nullptr; VulkanPushBuffer *pushVertex = nullptr;
VulkanPushBuffer *pushIndex = nullptr; VulkanPushBuffer *pushIndex = nullptr;
bool frameDescSetUpdated = false;
// We do rolling allocation and reset instead of caching across frames. That we might do later. // We do rolling allocation and reset instead of caching across frames. That we might do later.
DenseHashMap<DescriptorSetKey, VkDescriptorSet, (VkDescriptorSet)VK_NULL_HANDLE> descSets; DenseHashMap<DescriptorSetKey, VkDescriptorSet, (VkDescriptorSet)VK_NULL_HANDLE> descSets;

View File

@ -65,9 +65,9 @@ const char *uploadShader = R"(
// hardware vendors. // hardware vendors.
layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in; layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
uniform layout(binding = 0, rgba8) writeonly image2D img; uniform layout(set = 1, binding = 0, rgba8) writeonly image2D img;
layout(std430, binding = 1) buffer Buf { layout(std430, set = 1, binding = 1) buffer Buf {
uint data[]; uint data[];
} buf; } buf;
@ -251,7 +251,7 @@ void TextureCacheVulkan::DeviceRestore(Draw::DrawContext *draw) {
CompileScalingShader(); CompileScalingShader();
computeShaderManager_.DeviceRestore(vulkan); computeShaderManager_.DeviceRestore(draw);
} }
void TextureCacheVulkan::NotifyConfigChanged() { void TextureCacheVulkan::NotifyConfigChanged() {
@ -626,7 +626,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
VK_PROFILE_BEGIN(vulkan, cmdInit, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PROFILE_BEGIN(vulkan, cmdInit, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
"Compute Upload: %dx%d->%dx%d", mipUnscaledWidth, mipUnscaledHeight, mipWidth, mipHeight); "Compute Upload: %dx%d->%dx%d", mipUnscaledWidth, mipUnscaledHeight, mipWidth, mipHeight);
vkCmdBindPipeline(cmdInit, VK_PIPELINE_BIND_POINT_COMPUTE, computeShaderManager_.GetPipeline(uploadCS_)); vkCmdBindPipeline(cmdInit, VK_PIPELINE_BIND_POINT_COMPUTE, computeShaderManager_.GetPipeline(uploadCS_));
vkCmdBindDescriptorSets(cmdInit, VK_PIPELINE_BIND_POINT_COMPUTE, computeShaderManager_.GetPipelineLayout(), 0, 1, &descSet, 0, nullptr); vkCmdBindDescriptorSets(cmdInit, VK_PIPELINE_BIND_POINT_COMPUTE, computeShaderManager_.GetPipelineLayout(), 1, 1, &descSet, 0, nullptr);
vkCmdPushConstants(cmdInit, computeShaderManager_.GetPipelineLayout(), VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(params), &params); vkCmdPushConstants(cmdInit, computeShaderManager_.GetPipelineLayout(), VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(params), &params);
vkCmdDispatch(cmdInit, (mipUnscaledWidth + 7) / 8, (mipUnscaledHeight + 7) / 8, 1); vkCmdDispatch(cmdInit, (mipUnscaledWidth + 7) / 8, (mipUnscaledHeight + 7) / 8, 1);
VK_PROFILE_END(vulkan, cmdInit, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); VK_PROFILE_END(vulkan, cmdInit, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);

View File

@ -56,7 +56,7 @@ VulkanComputeShaderManager::VulkanComputeShaderManager(VulkanContext *vulkan) :
} }
VulkanComputeShaderManager::~VulkanComputeShaderManager() {} VulkanComputeShaderManager::~VulkanComputeShaderManager() {}
void VulkanComputeShaderManager::InitDeviceObjects() { void VulkanComputeShaderManager::InitDeviceObjects(Draw::DrawContext *draw) {
VkPipelineCacheCreateInfo pc{ VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO }; VkPipelineCacheCreateInfo pc{ VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO };
VkResult res = vkCreatePipelineCache(vulkan_->GetDevice(), &pc, nullptr, &pipelineCache_); VkResult res = vkCreatePipelineCache(vulkan_->GetDevice(), &pc, nullptr, &pipelineCache_);
_assert_(VK_SUCCESS == res); _assert_(VK_SUCCESS == res);
@ -106,8 +106,10 @@ void VulkanComputeShaderManager::InitDeviceObjects() {
VkPipelineLayoutCreateInfo pl = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO }; VkPipelineLayoutCreateInfo pl = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
pl.pPushConstantRanges = &push; pl.pPushConstantRanges = &push;
pl.pushConstantRangeCount = 1; pl.pushConstantRangeCount = 1;
pl.setLayoutCount = 1; VkDescriptorSetLayout frameDescSetLayout = (VkDescriptorSetLayout)draw->GetNativeObject(Draw::NativeObject::FRAME_DATA_DESC_SET_LAYOUT);
pl.pSetLayouts = &descriptorSetLayout_; VkDescriptorSetLayout setLayouts[2] = { frameDescSetLayout, descriptorSetLayout_ };
pl.setLayoutCount = ARRAY_SIZE(setLayouts);
pl.pSetLayouts = setLayouts;
pl.flags = 0; pl.flags = 0;
res = vkCreatePipelineLayout(device, &pl, nullptr, &pipelineLayout_); res = vkCreatePipelineLayout(device, &pl, nullptr, &pipelineLayout_);
_assert_(VK_SUCCESS == res); _assert_(VK_SUCCESS == res);

View File

@ -25,6 +25,7 @@
#include "Common/GPU/Vulkan/VulkanImage.h" #include "Common/GPU/Vulkan/VulkanImage.h"
#include "Common/GPU/Vulkan/VulkanLoader.h" #include "Common/GPU/Vulkan/VulkanLoader.h"
#include "Common/GPU/Vulkan/VulkanMemory.h" #include "Common/GPU/Vulkan/VulkanMemory.h"
#include "Common/GPU/thin3d.h"
extern const VkComponentMapping VULKAN_4444_SWIZZLE; extern const VkComponentMapping VULKAN_4444_SWIZZLE;
extern const VkComponentMapping VULKAN_1555_SWIZZLE; extern const VkComponentMapping VULKAN_1555_SWIZZLE;
@ -47,9 +48,9 @@ public:
void DeviceLost() { void DeviceLost() {
DestroyDeviceObjects(); DestroyDeviceObjects();
} }
void DeviceRestore(VulkanContext *vulkan) { void DeviceRestore(Draw::DrawContext *draw) {
vulkan_ = vulkan; vulkan_ = (VulkanContext *)draw->GetNativeObject(Draw::NativeObject::CONTEXT);
InitDeviceObjects(); InitDeviceObjects(draw);
} }
// Note: This doesn't cache. The descriptor is for immediate use only. // Note: This doesn't cache. The descriptor is for immediate use only.
@ -63,7 +64,7 @@ public:
void EndFrame(); void EndFrame();
private: private:
void InitDeviceObjects(); void InitDeviceObjects(Draw::DrawContext *draw);
void DestroyDeviceObjects(); void DestroyDeviceObjects();
VulkanContext *vulkan_ = nullptr; VulkanContext *vulkan_ = nullptr;

View File

@ -44,7 +44,7 @@ static const std::vector<Draw::ShaderSource> fsDiscard = {
layout(location = 0) in vec4 oColor0; layout(location = 0) in vec4 oColor0;
layout(location = 1) in vec2 oTexCoord0; layout(location = 1) in vec2 oTexCoord0;
layout(location = 0) out vec4 fragColor0; layout(location = 0) out vec4 fragColor0;
layout(set = 0, binding = 1) uniform sampler2D Sampler0; layout(set = 1, binding = 1) uniform sampler2D Sampler0;
void main() { void main() {
vec4 color = texture(Sampler0, oTexCoord0) * oColor0; vec4 color = texture(Sampler0, oTexCoord0) * oColor0;
if (color.a <= 0.0) if (color.a <= 0.0)
@ -86,7 +86,7 @@ static const std::vector<Draw::ShaderSource> fsAdrenoLogicTest = {
layout(location = 0) in vec4 oColor0; layout(location = 0) in vec4 oColor0;
layout(location = 1) in highp vec2 oTexCoord0; layout(location = 1) in highp vec2 oTexCoord0;
layout(location = 0) out vec4 fragColor0; layout(location = 0) out vec4 fragColor0;
layout(set = 0, binding = 1) uniform sampler2D Sampler0; layout(set = 1, binding = 1) uniform sampler2D Sampler0;
void main() { void main() {
vec4 v = texture(Sampler0, oTexCoord0).aaaa * oColor0; vec4 v = texture(Sampler0, oTexCoord0).aaaa * oColor0;
if (v.r < 0.2 && v.g < 0.2 && v.b < 0.2) discard; if (v.r < 0.2 && v.g < 0.2 && v.b < 0.2) discard;
@ -117,7 +117,7 @@ static const std::vector<Draw::ShaderSource> vsAdrenoLogicTest = {
"#version 450\n" "#version 450\n"
"#extension GL_ARB_separate_shader_objects : enable\n" "#extension GL_ARB_separate_shader_objects : enable\n"
"#extension GL_ARB_shading_language_420pack : enable\n" "#extension GL_ARB_shading_language_420pack : enable\n"
"layout (std140, set = 0, binding = 0) uniform bufferVals {\n" "layout (std140, set = 1, binding = 0) uniform bufferVals {\n"
" mat4 WorldViewProj;\n" " mat4 WorldViewProj;\n"
"} myBufferVals;\n" "} myBufferVals;\n"
"layout (location = 0) in vec4 pos;\n" "layout (location = 0) in vec4 pos;\n"
@ -173,7 +173,7 @@ static const std::vector<Draw::ShaderSource> fsFlat = {
"layout(location = 0) flat in lowp vec4 oColor0;\n" "layout(location = 0) flat in lowp vec4 oColor0;\n"
"layout(location = 1) in highp vec2 oTexCoord0;\n" "layout(location = 1) in highp vec2 oTexCoord0;\n"
"layout(location = 0) out vec4 fragColor0;\n" "layout(location = 0) out vec4 fragColor0;\n"
"layout(set = 0, binding = 1) uniform sampler2D Sampler0;\n" "layout(set = 1, binding = 1) uniform sampler2D Sampler0;\n"
"void main() { fragColor0 = texture(Sampler0, oTexCoord0) * oColor0; }\n" "void main() { fragColor0 = texture(Sampler0, oTexCoord0) * oColor0; }\n"
} }
}; };
@ -214,7 +214,7 @@ static const std::vector<Draw::ShaderSource> vsFlat = {
"#version 450\n" "#version 450\n"
"#extension GL_ARB_separate_shader_objects : enable\n" "#extension GL_ARB_separate_shader_objects : enable\n"
"#extension GL_ARB_shading_language_420pack : enable\n" "#extension GL_ARB_shading_language_420pack : enable\n"
"layout (std140, set = 0, binding = 0) uniform bufferVals {\n" "layout (std140, set = 1, binding = 0) uniform bufferVals {\n"
" mat4 WorldViewProj;\n" " mat4 WorldViewProj;\n"
"} myBufferVals;\n" "} myBufferVals;\n"
"layout (location = 0) in vec4 pos;\n" "layout (location = 0) in vec4 pos;\n"