mirror of
https://github.com/love2d/love.git
synced 2026-08-17 19:23:38 +02:00
vulkan: improve handling of vertex attribute bindings.
This commit is contained in:
@@ -61,6 +61,9 @@ static const std::vector<const char*> deviceExtensions = {
|
|||||||
|
|
||||||
constexpr uint32_t USAGES_POLL_INTERVAL = 5000;
|
constexpr uint32_t USAGES_POLL_INTERVAL = 5000;
|
||||||
|
|
||||||
|
constexpr int DEFAULT_VERTEX_BUFFER_BINDING = 0;
|
||||||
|
constexpr int VERTEX_BUFFER_BINDING_START = 1;
|
||||||
|
|
||||||
VkDevice Graphics::getDevice() const
|
VkDevice Graphics::getDevice() const
|
||||||
{
|
{
|
||||||
return device;
|
return device;
|
||||||
@@ -152,8 +155,7 @@ Graphics::Graphics()
|
|||||||
|
|
||||||
Graphics::~Graphics()
|
Graphics::~Graphics()
|
||||||
{
|
{
|
||||||
defaultConstantTexCoord.set(nullptr);
|
defaultVertexBuffer.set(nullptr);
|
||||||
defaultConstantColor.set(nullptr);
|
|
||||||
localUniformBuffer.set(nullptr);
|
localUniformBuffer.set(nullptr);
|
||||||
|
|
||||||
Volatile::unloadAll();
|
Volatile::unloadAll();
|
||||||
@@ -623,22 +625,42 @@ bool Graphics::setMode(void *context, int width, int height, int pixelwidth, int
|
|||||||
batchedDrawState.indexBuffer = new StreamBuffer(this, BUFFERUSAGE_INDEX, sizeof(uint16) * LOVE_UINT16_MAX);
|
batchedDrawState.indexBuffer = new StreamBuffer(this, BUFFERUSAGE_INDEX, sizeof(uint16) * LOVE_UINT16_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
// sometimes the VertexTexCoord is not set, so we manually adjust it to (0, 0)
|
if (defaultVertexBuffer == nullptr)
|
||||||
if (defaultConstantTexCoord == nullptr)
|
|
||||||
{
|
{
|
||||||
float zeroTexCoord[2] = { 0.0f, 0.0f };
|
struct DefaultData
|
||||||
Buffer::DataDeclaration format("ConstantTexCoord", DATAFORMAT_FLOAT_VEC2);
|
{
|
||||||
Buffer::Settings settings(BUFFERUSAGEFLAG_VERTEX, BUFFERDATAUSAGE_STATIC);
|
float floats[4];
|
||||||
defaultConstantTexCoord = newBuffer(settings, { format }, zeroTexCoord, sizeof(zeroTexCoord), 1);
|
int ints[4];
|
||||||
}
|
float color[4];
|
||||||
|
} data;
|
||||||
|
|
||||||
|
data.floats[0] = 0.0f;
|
||||||
|
data.floats[1] = 0.0f;
|
||||||
|
data.floats[2] = 0.0f;
|
||||||
|
data.floats[3] = 1.0f;
|
||||||
|
|
||||||
|
data.ints[0] = 0;
|
||||||
|
data.ints[1] = 0;
|
||||||
|
data.ints[2] = 0;
|
||||||
|
data.ints[3] = 1;
|
||||||
|
|
||||||
|
data.color[0] = 1.0f;
|
||||||
|
data.color[1] = 1.0f;
|
||||||
|
data.color[2] = 1.0f;
|
||||||
|
data.color[3] = 1.0f;
|
||||||
|
|
||||||
|
std::vector<Buffer::DataDeclaration> format = {
|
||||||
|
Buffer::DataDeclaration("Floats", DATAFORMAT_FLOAT_VEC4),
|
||||||
|
Buffer::DataDeclaration("Ints", DATAFORMAT_INT32_VEC4),
|
||||||
|
Buffer::DataDeclaration("Color", DATAFORMAT_FLOAT_VEC4)
|
||||||
|
};
|
||||||
|
|
||||||
// sometimes the VertexColor is not set, so we manually adjust it to white color
|
|
||||||
if (defaultConstantColor == nullptr)
|
|
||||||
{
|
|
||||||
uint8 whiteColor[] = { 255, 255, 255, 255 };
|
|
||||||
Buffer::DataDeclaration format("ConstantColor", DATAFORMAT_UNORM8_VEC4);
|
|
||||||
Buffer::Settings settings(BUFFERUSAGEFLAG_VERTEX, BUFFERDATAUSAGE_STATIC);
|
Buffer::Settings settings(BUFFERUSAGEFLAG_VERTEX, BUFFERDATAUSAGE_STATIC);
|
||||||
defaultConstantColor = newBuffer(settings, { format }, whiteColor, sizeof(whiteColor), 1);
|
defaultVertexBuffer.set(newBuffer(settings, format, &data, sizeof(DefaultData), 1), Acquire::NORETAIN);
|
||||||
|
|
||||||
|
VkBuffer buffer = (VkBuffer)defaultVertexBuffer->getHandle();
|
||||||
|
VkDeviceSize offset = 0;
|
||||||
|
vkCmdBindVertexBuffers(commandBuffers.at(currentFrame), DEFAULT_VERTEX_BUFFER_BINDING, 1, &buffer, &offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
createDefaultShaders();
|
createDefaultShaders();
|
||||||
@@ -1295,6 +1317,13 @@ void Graphics::startRecordingGraphicsCommands()
|
|||||||
initDynamicState();
|
initDynamicState();
|
||||||
|
|
||||||
setDefaultRenderPass();
|
setDefaultRenderPass();
|
||||||
|
|
||||||
|
if (defaultVertexBuffer)
|
||||||
|
{
|
||||||
|
VkBuffer buffer = (VkBuffer)defaultVertexBuffer->getHandle();
|
||||||
|
VkDeviceSize offset = 0;
|
||||||
|
vkCmdBindVertexBuffers(commandBuffers.at(currentFrame), DEFAULT_VERTEX_BUFFER_BINDING, 1, &buffer, &offset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::endRecordingGraphicsCommands() {
|
void Graphics::endRecordingGraphicsCommands() {
|
||||||
@@ -2151,100 +2180,71 @@ VkRenderPass Graphics::getRenderPass(RenderPassConfiguration &configuration)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::createVulkanVertexFormat(
|
void Graphics::createVulkanVertexFormat(
|
||||||
VertexAttributes vertexAttributes,
|
Shader *shader,
|
||||||
|
const VertexAttributes &attributes,
|
||||||
std::vector<VkVertexInputBindingDescription> &bindingDescriptions,
|
std::vector<VkVertexInputBindingDescription> &bindingDescriptions,
|
||||||
std::vector<VkVertexInputAttributeDescription> &attributeDescriptions)
|
std::vector<VkVertexInputAttributeDescription> &attributeDescriptions)
|
||||||
{
|
{
|
||||||
std::set<uint32_t> usedBuffers;
|
std::set<uint32_t> usedBuffers;
|
||||||
|
|
||||||
auto enableBits = vertexAttributes.enableBits;
|
for (const auto &pair : shader->getVertexAttributeIndices())
|
||||||
auto allBits = enableBits;
|
|
||||||
|
|
||||||
bool usesColor = false;
|
|
||||||
bool usesTexCoord = false;
|
|
||||||
|
|
||||||
uint8_t highestBufferBinding = 0;
|
|
||||||
|
|
||||||
uint32_t i = 0;
|
|
||||||
while (allBits)
|
|
||||||
{
|
{
|
||||||
|
int i = pair.second;
|
||||||
uint32 bit = 1u << i;
|
uint32 bit = 1u << i;
|
||||||
if (enableBits & bit)
|
|
||||||
|
VkVertexInputAttributeDescription attribdesc{};
|
||||||
|
attribdesc.location = i;
|
||||||
|
|
||||||
|
if (attributes.enableBits & bit)
|
||||||
{
|
{
|
||||||
if (i == ATTRIB_TEXCOORD)
|
const auto &attrib = attributes.attribs[i];
|
||||||
usesTexCoord = true;
|
|
||||||
if (i == ATTRIB_COLOR)
|
|
||||||
usesColor = true;
|
|
||||||
|
|
||||||
auto attrib = vertexAttributes.attribs[i];
|
int bufferbinding = VERTEX_BUFFER_BINDING_START + attrib.bufferIndex;
|
||||||
auto bufferBinding = attrib.bufferIndex;
|
|
||||||
if (usedBuffers.find(bufferBinding) == usedBuffers.end())
|
attribdesc.binding = bufferbinding;
|
||||||
|
attribdesc.offset = attrib.offsetFromVertex;
|
||||||
|
attribdesc.format = Vulkan::getVulkanVertexFormat(attrib.getFormat());
|
||||||
|
|
||||||
|
if (usedBuffers.find(bufferbinding) == usedBuffers.end())
|
||||||
{
|
{
|
||||||
usedBuffers.insert(bufferBinding);
|
usedBuffers.insert(bufferbinding);
|
||||||
|
|
||||||
VkVertexInputBindingDescription bindingDescription{};
|
VkVertexInputBindingDescription bindingdesc{};
|
||||||
bindingDescription.binding = bufferBinding;
|
bindingdesc.binding = bufferbinding;
|
||||||
if (vertexAttributes.instanceBits & (1u << bufferBinding))
|
if (attributes.instanceBits & (1u << attrib.bufferIndex))
|
||||||
bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
|
bindingdesc.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
|
||||||
else
|
else
|
||||||
bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
bindingdesc.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||||
bindingDescription.stride = vertexAttributes.bufferLayouts[bufferBinding].stride;
|
bindingdesc.stride = attributes.bufferLayouts[attrib.bufferIndex].stride;
|
||||||
bindingDescriptions.push_back(bindingDescription);
|
bindingDescriptions.push_back(bindingdesc);
|
||||||
|
|
||||||
highestBufferBinding = std::max(highestBufferBinding, bufferBinding);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
attribdesc.binding = DEFAULT_VERTEX_BUFFER_BINDING;
|
||||||
|
|
||||||
VkVertexInputAttributeDescription attributeDescription{};
|
// Indices should match the creation parameters for defaultVertexBuffer.
|
||||||
attributeDescription.location = i;
|
// TODO: handle int/uint attributes?
|
||||||
attributeDescription.binding = bufferBinding;
|
if (i == ATTRIB_COLOR)
|
||||||
attributeDescription.offset = attrib.offsetFromVertex;
|
attribdesc.offset = defaultVertexBuffer->getDataMember(2).offset;
|
||||||
attributeDescription.format = Vulkan::getVulkanVertexFormat(attrib.getFormat());
|
else
|
||||||
|
attribdesc.offset = defaultVertexBuffer->getDataMember(0).offset;
|
||||||
|
|
||||||
attributeDescriptions.push_back(attributeDescription);
|
attribdesc.format = Vulkan::getVulkanVertexFormat(DATAFORMAT_FLOAT_VEC4);
|
||||||
|
|
||||||
|
if (usedBuffers.find(DEFAULT_VERTEX_BUFFER_BINDING) == usedBuffers.end())
|
||||||
|
{
|
||||||
|
usedBuffers.insert(DEFAULT_VERTEX_BUFFER_BINDING);
|
||||||
|
|
||||||
|
VkVertexInputBindingDescription bindingdesc{};
|
||||||
|
bindingdesc.binding = DEFAULT_VERTEX_BUFFER_BINDING;
|
||||||
|
bindingdesc.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||||
|
bindingdesc.stride = 0; // no stride, will always read the same coord multiple times.
|
||||||
|
bindingDescriptions.push_back(bindingdesc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i++;
|
attributeDescriptions.push_back(attribdesc);
|
||||||
allBits >>= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!usesTexCoord)
|
|
||||||
{
|
|
||||||
// FIXME: is there a case where gaps happen between buffer bindings?
|
|
||||||
// then this doesn't work. We might need to enable null buffers again.
|
|
||||||
const auto constantTexCoordBufferBinding = ++highestBufferBinding;
|
|
||||||
|
|
||||||
VkVertexInputBindingDescription bindingDescription{};
|
|
||||||
bindingDescription.binding = constantTexCoordBufferBinding;
|
|
||||||
bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
|
||||||
bindingDescription.stride = 0; // no stride, will always read the same coord multiple times.
|
|
||||||
bindingDescriptions.push_back(bindingDescription);
|
|
||||||
|
|
||||||
VkVertexInputAttributeDescription attributeDescription{};
|
|
||||||
attributeDescription.binding = constantTexCoordBufferBinding;
|
|
||||||
attributeDescription.location = ATTRIB_TEXCOORD;
|
|
||||||
attributeDescription.offset = 0;
|
|
||||||
attributeDescription.format = VK_FORMAT_R32G32_SFLOAT;
|
|
||||||
attributeDescriptions.push_back(attributeDescription);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!usesColor)
|
|
||||||
{
|
|
||||||
// FIXME: is there a case where gaps happen between buffer bindings?
|
|
||||||
// then this doesn't work. We might need to enable null buffers again.
|
|
||||||
const auto constantColorBufferBinding = ++highestBufferBinding;
|
|
||||||
|
|
||||||
VkVertexInputBindingDescription bindingDescription{};
|
|
||||||
bindingDescription.binding = constantColorBufferBinding;
|
|
||||||
bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
|
||||||
bindingDescription.stride = 0; // no stride, will always read the same color multiple times.
|
|
||||||
bindingDescriptions.push_back(bindingDescription);
|
|
||||||
|
|
||||||
VkVertexInputAttributeDescription attributeDescription{};
|
|
||||||
attributeDescription.binding = constantColorBufferBinding;
|
|
||||||
attributeDescription.location = ATTRIB_COLOR;
|
|
||||||
attributeDescription.offset = 0;
|
|
||||||
attributeDescription.format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
|
||||||
attributeDescriptions.push_back(attributeDescription);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2279,9 +2279,15 @@ void Graphics::prepareDraw(const VertexAttributes &attributes, const BufferBindi
|
|||||||
configuration.dynamicState.cullmode = cullmode;
|
configuration.dynamicState.cullmode = cullmode;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkBuffer vkbuffers[VertexAttributes::MAX + 2];
|
configuration.shader->setMainTex(texture);
|
||||||
VkDeviceSize vkoffsets[VertexAttributes::MAX + 2];
|
|
||||||
int buffercount = 0;
|
ensureGraphicsPipelineConfiguration(configuration);
|
||||||
|
|
||||||
|
configuration.shader->cmdPushDescriptorSets(commandBuffers.at(currentFrame), VK_PIPELINE_BIND_POINT_GRAPHICS);
|
||||||
|
|
||||||
|
VkBuffer vkbuffers[BufferBindings::MAX];
|
||||||
|
VkDeviceSize vkoffsets[BufferBindings::MAX];
|
||||||
|
uint32 buffercount = 0;
|
||||||
|
|
||||||
uint32 allbits = buffers.useBits;
|
uint32 allbits = buffers.useBits;
|
||||||
uint32 i = 0;
|
uint32 i = 0;
|
||||||
@@ -2289,6 +2295,7 @@ void Graphics::prepareDraw(const VertexAttributes &attributes, const BufferBindi
|
|||||||
{
|
{
|
||||||
uint32 bit = 1u << i;
|
uint32 bit = 1u << i;
|
||||||
|
|
||||||
|
// TODO: handle split ranges.
|
||||||
if (buffers.useBits & bit)
|
if (buffers.useBits & bit)
|
||||||
{
|
{
|
||||||
vkbuffers[buffercount] = (VkBuffer)buffers.info[i].buffer->getHandle();
|
vkbuffers[buffercount] = (VkBuffer)buffers.info[i].buffer->getHandle();
|
||||||
@@ -2300,28 +2307,8 @@ void Graphics::prepareDraw(const VertexAttributes &attributes, const BufferBindi
|
|||||||
allbits >>= 1;
|
allbits >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(attributes.enableBits & (1u << ATTRIB_TEXCOORD)))
|
|
||||||
{
|
|
||||||
vkbuffers[buffercount] = (VkBuffer)defaultConstantTexCoord->getHandle();
|
|
||||||
vkoffsets[buffercount] = (VkDeviceSize)0;
|
|
||||||
buffercount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(attributes.enableBits & (1u << ATTRIB_COLOR)))
|
|
||||||
{
|
|
||||||
vkbuffers[buffercount] = (VkBuffer)defaultConstantColor->getHandle();
|
|
||||||
vkoffsets[buffercount] = (VkDeviceSize)0;
|
|
||||||
buffercount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
configuration.shader->setMainTex(texture);
|
|
||||||
|
|
||||||
ensureGraphicsPipelineConfiguration(configuration);
|
|
||||||
|
|
||||||
configuration.shader->cmdPushDescriptorSets(commandBuffers.at(currentFrame), VK_PIPELINE_BIND_POINT_GRAPHICS);
|
|
||||||
|
|
||||||
if (buffercount > 0)
|
if (buffercount > 0)
|
||||||
vkCmdBindVertexBuffers(commandBuffers.at(currentFrame), 0, static_cast<uint32_t>(buffercount), vkbuffers, vkoffsets);
|
vkCmdBindVertexBuffers(commandBuffers.at(currentFrame), VERTEX_BUFFER_BINDING_START, buffercount, vkbuffers, vkoffsets);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::setDefaultRenderPass()
|
void Graphics::setDefaultRenderPass()
|
||||||
@@ -2586,7 +2573,7 @@ VkPipeline Graphics::createGraphicsPipeline(GraphicsPipelineConfiguration &confi
|
|||||||
std::vector<VkVertexInputBindingDescription> bindingDescriptions;
|
std::vector<VkVertexInputBindingDescription> bindingDescriptions;
|
||||||
std::vector<VkVertexInputAttributeDescription> attributeDescriptions;
|
std::vector<VkVertexInputAttributeDescription> attributeDescriptions;
|
||||||
|
|
||||||
createVulkanVertexFormat(configuration.vertexAttributes, bindingDescriptions, attributeDescriptions);
|
createVulkanVertexFormat(configuration.shader, configuration.vertexAttributes, bindingDescriptions, attributeDescriptions);
|
||||||
|
|
||||||
VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
|
VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
|
||||||
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||||
|
|||||||
@@ -366,7 +366,8 @@ private:
|
|||||||
void endRecordingGraphicsCommands();
|
void endRecordingGraphicsCommands();
|
||||||
void ensureGraphicsPipelineConfiguration(GraphicsPipelineConfiguration &configuration);
|
void ensureGraphicsPipelineConfiguration(GraphicsPipelineConfiguration &configuration);
|
||||||
void createVulkanVertexFormat(
|
void createVulkanVertexFormat(
|
||||||
VertexAttributes vertexAttributes,
|
Shader *shader,
|
||||||
|
const VertexAttributes &attributes,
|
||||||
std::vector<VkVertexInputBindingDescription> &bindingDescriptions,
|
std::vector<VkVertexInputBindingDescription> &bindingDescriptions,
|
||||||
std::vector<VkVertexInputAttributeDescription> &attributeDescriptions);
|
std::vector<VkVertexInputAttributeDescription> &attributeDescriptions);
|
||||||
void prepareDraw(
|
void prepareDraw(
|
||||||
@@ -430,8 +431,7 @@ private:
|
|||||||
bool swapChainRecreationRequested = false;
|
bool swapChainRecreationRequested = false;
|
||||||
bool transitionColorDepthLayouts = false;
|
bool transitionColorDepthLayouts = false;
|
||||||
VmaAllocator vmaAllocator = VK_NULL_HANDLE;
|
VmaAllocator vmaAllocator = VK_NULL_HANDLE;
|
||||||
StrongRef<love::graphics::Buffer> defaultConstantColor;
|
StrongRef<love::graphics::Buffer> defaultVertexBuffer;
|
||||||
StrongRef<love::graphics::Buffer> defaultConstantTexCoord;
|
|
||||||
StrongRef<StreamBuffer> localUniformBuffer;
|
StrongRef<StreamBuffer> localUniformBuffer;
|
||||||
// functions that need to be called to cleanup objects that were needed for rendering a frame.
|
// functions that need to be called to cleanup objects that were needed for rendering a frame.
|
||||||
// We need a vector for each frame in flight.
|
// We need a vector for each frame in flight.
|
||||||
|
|||||||
@@ -552,18 +552,28 @@ void Shader::compileShaders()
|
|||||||
glslang::SpvOptions opt;
|
glslang::SpvOptions opt;
|
||||||
opt.validate = true;
|
opt.validate = true;
|
||||||
|
|
||||||
std::vector<uint32_t> spirv;
|
std::vector<uint32> spirv;
|
||||||
|
|
||||||
GlslangToSpv(*intermediate, spirv, &logger, &opt);
|
GlslangToSpv(*intermediate, spirv, &logger, &opt);
|
||||||
|
|
||||||
spirv_cross::CompilerGLSL comp(spirv);
|
auto compiler = std::make_unique<spirv_cross::CompilerGLSL>(spirv);
|
||||||
|
auto &comp = *compiler;
|
||||||
|
|
||||||
// we only care about variables that are actually getting used.
|
// We aren't recompiling the SPIR-V to something else, so
|
||||||
auto active = comp.get_active_interface_variables();
|
// set_enabled_interface_variables wouldn't do much.
|
||||||
auto shaderResources = comp.get_shader_resources(active);
|
// Vulkan has various rules about making sure bindings to inputs and
|
||||||
comp.set_enabled_interface_variables(std::move(active));
|
// resources are valid, so we can't skip inactive ones here.
|
||||||
|
// Unfortunately GlslangToSpv doesn't strip unused resources even
|
||||||
|
// though it knows about them...
|
||||||
|
auto active = compiler->get_active_interface_variables();
|
||||||
|
auto shaderResources = comp.get_shader_resources();
|
||||||
|
|
||||||
for (const auto &resource : shaderResources.uniform_buffers)
|
for (const auto &resource : shaderResources.uniform_buffers)
|
||||||
{
|
{
|
||||||
|
// TODO: Do something smarter here.
|
||||||
|
if (active.find(resource.id) == active.end())
|
||||||
|
continue;
|
||||||
|
|
||||||
if (resource.name == "gl_DefaultUniformBlock")
|
if (resource.name == "gl_DefaultUniformBlock")
|
||||||
{
|
{
|
||||||
const auto &type = comp.get_type(resource.base_type_id);
|
const auto &type = comp.get_type(resource.base_type_id);
|
||||||
@@ -587,6 +597,10 @@ void Shader::compileShaders()
|
|||||||
|
|
||||||
for (const auto &r : shaderResources.sampled_images)
|
for (const auto &r : shaderResources.sampled_images)
|
||||||
{
|
{
|
||||||
|
// TODO: Do something smarter here.
|
||||||
|
if (active.find(r.id) == active.end())
|
||||||
|
continue;
|
||||||
|
|
||||||
std::string name = canonicaliizeUniformName(r.name);
|
std::string name = canonicaliizeUniformName(r.name);
|
||||||
auto uniformit = reflection.allUniforms.find(name);
|
auto uniformit = reflection.allUniforms.find(name);
|
||||||
if (uniformit == reflection.allUniforms.end())
|
if (uniformit == reflection.allUniforms.end())
|
||||||
@@ -606,6 +620,10 @@ void Shader::compileShaders()
|
|||||||
|
|
||||||
for (const auto &r : shaderResources.storage_buffers)
|
for (const auto &r : shaderResources.storage_buffers)
|
||||||
{
|
{
|
||||||
|
// TODO: Do something smarter here.
|
||||||
|
if (active.find(r.id) == active.end())
|
||||||
|
continue;
|
||||||
|
|
||||||
std::string name = canonicaliizeUniformName(r.name);
|
std::string name = canonicaliizeUniformName(r.name);
|
||||||
const auto &uniformit = reflection.storageBuffers.find(name);
|
const auto &uniformit = reflection.storageBuffers.find(name);
|
||||||
if (uniformit == reflection.storageBuffers.end())
|
if (uniformit == reflection.storageBuffers.end())
|
||||||
@@ -621,6 +639,10 @@ void Shader::compileShaders()
|
|||||||
|
|
||||||
for (const auto &r : shaderResources.storage_images)
|
for (const auto &r : shaderResources.storage_images)
|
||||||
{
|
{
|
||||||
|
// TODO: Do something smarter here.
|
||||||
|
if (active.find(r.id) == active.end())
|
||||||
|
continue;
|
||||||
|
|
||||||
std::string name = canonicaliizeUniformName(r.name);
|
std::string name = canonicaliizeUniformName(r.name);
|
||||||
const auto &uniformit = reflection.storageTextures.find(name);
|
const auto &uniformit = reflection.storageTextures.find(name);
|
||||||
if (uniformit == reflection.storageTextures.end())
|
if (uniformit == reflection.storageTextures.end())
|
||||||
@@ -638,6 +660,8 @@ void Shader::compileShaders()
|
|||||||
{
|
{
|
||||||
int nextAttributeIndex = ATTRIB_MAX_ENUM;
|
int nextAttributeIndex = ATTRIB_MAX_ENUM;
|
||||||
|
|
||||||
|
// Don't skip unused inputs, vulkan still needs to have valid
|
||||||
|
// bindings for them.
|
||||||
for (const auto &r : shaderResources.stage_inputs)
|
for (const auto &r : shaderResources.stage_inputs)
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
@@ -699,7 +723,7 @@ void Shader::compileShaders()
|
|||||||
if (localUniformData.size() > 0)
|
if (localUniformData.size() > 0)
|
||||||
numBuffers++;
|
numBuffers++;
|
||||||
|
|
||||||
for (const auto kvp : reflection.allUniforms)
|
for (const auto &kvp : reflection.allUniforms)
|
||||||
{
|
{
|
||||||
if (!kvp.second->active)
|
if (!kvp.second->active)
|
||||||
continue;
|
continue;
|
||||||
@@ -925,7 +949,7 @@ void Shader::createDescriptorPoolSizes()
|
|||||||
|
|
||||||
for (const auto &entry : reflection.allUniforms)
|
for (const auto &entry : reflection.allUniforms)
|
||||||
{
|
{
|
||||||
if (entry.second->location < 0)
|
if (!entry.second->active)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
VkDescriptorPoolSize size{};
|
VkDescriptorPoolSize size{};
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ public:
|
|||||||
std::string getWarnings() const override { return ""; }
|
std::string getWarnings() const override { return ""; }
|
||||||
|
|
||||||
int getVertexAttributeIndex(const std::string &name) override;
|
int getVertexAttributeIndex(const std::string &name) override;
|
||||||
|
const std::unordered_map<std::string, int> getVertexAttributeIndices() const { return attributes; }
|
||||||
|
|
||||||
const UniformInfo *getUniformInfo(BuiltinUniform builtin) const override;
|
const UniformInfo *getUniformInfo(BuiltinUniform builtin) const override;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user