mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-02 01:24:11 +01:00
[dxvk] Use packed input layout state
Also move attribute and binding descriptions to the end so that comparisons are more likely to fail early.
This commit is contained in:
parent
c0ae4e38eb
commit
a5ab88d8f2
@ -2259,28 +2259,24 @@ namespace dxvk {
|
||||
DxvkContextFlag::GpDirtyVertexBuffers);
|
||||
|
||||
for (uint32_t i = 0; i < attributeCount; i++) {
|
||||
m_state.gp.state.ilAttributes[i].location = attributes[i].location;
|
||||
m_state.gp.state.ilAttributes[i].binding = attributes[i].binding;
|
||||
m_state.gp.state.ilAttributes[i].format = attributes[i].format;
|
||||
m_state.gp.state.ilAttributes[i].offset = attributes[i].offset;
|
||||
m_state.gp.state.ilAttributes[i] = DxvkIlAttribute(
|
||||
attributes[i].location, attributes[i].binding,
|
||||
attributes[i].format, attributes[i].offset);
|
||||
}
|
||||
|
||||
for (uint32_t i = attributeCount; i < m_state.gp.state.ilAttributeCount; i++)
|
||||
m_state.gp.state.ilAttributes[i] = VkVertexInputAttributeDescription();
|
||||
for (uint32_t i = attributeCount; i < m_state.gp.state.il.attributeCount(); i++)
|
||||
m_state.gp.state.ilAttributes[i] = DxvkIlAttribute();
|
||||
|
||||
for (uint32_t i = 0; i < bindingCount; i++) {
|
||||
m_state.gp.state.ilBindings[i].binding = bindings[i].binding;
|
||||
m_state.gp.state.ilBindings[i].inputRate = bindings[i].inputRate;
|
||||
m_state.gp.state.ilDivisors[i] = bindings[i].fetchRate;
|
||||
m_state.gp.state.ilBindings[i] = DxvkIlBinding(
|
||||
bindings[i].binding, 0, bindings[i].inputRate,
|
||||
bindings[i].fetchRate);
|
||||
}
|
||||
|
||||
for (uint32_t i = bindingCount; i < m_state.gp.state.ilBindingCount; i++) {
|
||||
m_state.gp.state.ilBindings[i] = VkVertexInputBindingDescription();
|
||||
m_state.gp.state.ilDivisors[i] = 0;
|
||||
}
|
||||
for (uint32_t i = bindingCount; i < m_state.gp.state.il.bindingCount(); i++)
|
||||
m_state.gp.state.ilBindings[i] = DxvkIlBinding();
|
||||
|
||||
m_state.gp.state.ilAttributeCount = attributeCount;
|
||||
m_state.gp.state.ilBindingCount = bindingCount;
|
||||
m_state.gp.state.il = DxvkIlInfo(attributeCount, bindingCount);
|
||||
}
|
||||
|
||||
|
||||
@ -3620,9 +3616,9 @@ namespace dxvk {
|
||||
this->pauseTransformFeedback();
|
||||
|
||||
// Set up vertex buffer strides for active bindings
|
||||
for (uint32_t i = 0; i < m_state.gp.state.ilBindingCount; i++) {
|
||||
const uint32_t binding = m_state.gp.state.ilBindings[i].binding;
|
||||
m_state.gp.state.ilBindings[i].stride = m_state.vi.vertexStrides[binding];
|
||||
for (uint32_t i = 0; i < m_state.gp.state.il.bindingCount(); i++) {
|
||||
const uint32_t binding = m_state.gp.state.ilBindings[i].binding();
|
||||
m_state.gp.state.ilBindings[i].setStride(m_state.vi.vertexStrides[binding]);
|
||||
}
|
||||
|
||||
// Check which dynamic states need to be active. States that
|
||||
@ -4015,15 +4011,15 @@ namespace dxvk {
|
||||
void DxvkContext::updateVertexBufferBindings() {
|
||||
m_flags.clr(DxvkContextFlag::GpDirtyVertexBuffers);
|
||||
|
||||
if (unlikely(!m_state.gp.state.ilBindingCount))
|
||||
if (unlikely(!m_state.gp.state.il.bindingCount()))
|
||||
return;
|
||||
|
||||
std::array<VkBuffer, MaxNumVertexBindings> buffers;
|
||||
std::array<VkDeviceSize, MaxNumVertexBindings> offsets;
|
||||
|
||||
// Set buffer handles and offsets for active bindings
|
||||
for (uint32_t i = 0; i < m_state.gp.state.ilBindingCount; i++) {
|
||||
uint32_t binding = m_state.gp.state.ilBindings[i].binding;
|
||||
for (uint32_t i = 0; i < m_state.gp.state.il.bindingCount(); i++) {
|
||||
uint32_t binding = m_state.gp.state.ilBindings[i].binding();
|
||||
|
||||
if (likely(m_state.vi.vertexBuffers[binding].defined())) {
|
||||
auto vbo = m_state.vi.vertexBuffers[binding].getDescriptor();
|
||||
@ -4042,7 +4038,7 @@ namespace dxvk {
|
||||
// Vertex bindigs get remapped when compiling the
|
||||
// pipeline, so this actually does the right thing
|
||||
m_cmd->cmdBindVertexBuffers(
|
||||
0, m_state.gp.state.ilBindingCount,
|
||||
0, m_state.gp.state.il.bindingCount(),
|
||||
buffers.data(), offsets.data());
|
||||
}
|
||||
|
||||
|
@ -231,14 +231,14 @@ namespace dxvk {
|
||||
// Generate per-instance attribute divisors
|
||||
std::array<VkVertexInputBindingDivisorDescriptionEXT, MaxNumVertexBindings> viDivisorDesc;
|
||||
uint32_t viDivisorCount = 0;
|
||||
|
||||
for (uint32_t i = 0; i < state.ilBindingCount; i++) {
|
||||
if (state.ilBindings[i].inputRate == VK_VERTEX_INPUT_RATE_INSTANCE
|
||||
&& state.ilDivisors[i] != 1) {
|
||||
|
||||
for (uint32_t i = 0; i < state.il.bindingCount(); i++) {
|
||||
if (state.ilBindings[i].inputRate() == VK_VERTEX_INPUT_RATE_INSTANCE
|
||||
&& state.ilBindings[i].divisor() != 1) {
|
||||
const uint32_t id = viDivisorCount++;
|
||||
|
||||
viDivisorDesc[id].binding = i;
|
||||
viDivisorDesc[id].divisor = state.ilDivisors[i];
|
||||
viDivisorDesc[id].binding = i; /* see below */
|
||||
viDivisorDesc[id].divisor = state.ilBindings[i].divisor();
|
||||
}
|
||||
}
|
||||
|
||||
@ -251,15 +251,15 @@ namespace dxvk {
|
||||
std::array<VkVertexInputBindingDescription, MaxNumVertexBindings> viBindings;
|
||||
std::array<uint32_t, MaxNumVertexBindings> viBindingMap = { };
|
||||
|
||||
for (uint32_t i = 0; i < state.ilBindingCount; i++) {
|
||||
viBindings[i] = state.ilBindings[i];
|
||||
for (uint32_t i = 0; i < state.il.bindingCount(); i++) {
|
||||
viBindings[i] = state.ilBindings[i].description();
|
||||
viBindings[i].binding = i;
|
||||
viBindingMap[state.ilBindings[i].binding] = i;
|
||||
viBindingMap[state.ilBindings[i].binding()] = i;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < state.ilAttributeCount; i++) {
|
||||
viAttribs[i] = state.ilAttributes[i];
|
||||
viAttribs[i].binding = viBindingMap[state.ilAttributes[i].binding];
|
||||
for (uint32_t i = 0; i < state.il.attributeCount(); i++) {
|
||||
viAttribs[i] = state.ilAttributes[i].description();
|
||||
viAttribs[i].binding = viBindingMap[state.ilAttributes[i].binding()];
|
||||
}
|
||||
|
||||
VkPipelineVertexInputDivisorStateCreateInfoEXT viDivisorInfo;
|
||||
@ -272,9 +272,9 @@ namespace dxvk {
|
||||
viInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||
viInfo.pNext = &viDivisorInfo;
|
||||
viInfo.flags = 0;
|
||||
viInfo.vertexBindingDescriptionCount = state.ilBindingCount;
|
||||
viInfo.vertexBindingDescriptionCount = state.il.bindingCount();
|
||||
viInfo.pVertexBindingDescriptions = viBindings.data();
|
||||
viInfo.vertexAttributeDescriptionCount = state.ilAttributeCount;
|
||||
viInfo.vertexAttributeDescriptionCount = state.il.attributeCount();
|
||||
viInfo.pVertexAttributeDescriptions = viAttribs.data();
|
||||
|
||||
if (viDivisorCount == 0)
|
||||
@ -453,8 +453,8 @@ namespace dxvk {
|
||||
// vertex shader must be provided by the input layout.
|
||||
uint32_t providedVertexInputs = 0;
|
||||
|
||||
for (uint32_t i = 0; i < state.ilAttributeCount; i++)
|
||||
providedVertexInputs |= 1u << state.ilAttributes[i].location;
|
||||
for (uint32_t i = 0; i < state.il.attributeCount(); i++)
|
||||
providedVertexInputs |= 1u << state.ilAttributes[i].location();
|
||||
|
||||
if ((providedVertexInputs & m_vsIn) != m_vsIn)
|
||||
return false;
|
||||
@ -470,8 +470,8 @@ namespace dxvk {
|
||||
return false;
|
||||
|
||||
// Prevent unintended out-of-bounds access to the IL arrays
|
||||
if (state.ilAttributeCount > DxvkLimits::MaxNumVertexAttributes
|
||||
|| state.ilBindingCount > DxvkLimits::MaxNumVertexBindings)
|
||||
if (state.il.attributeCount() > DxvkLimits::MaxNumVertexAttributes
|
||||
|| state.il.bindingCount() > DxvkLimits::MaxNumVertexBindings)
|
||||
return false;
|
||||
|
||||
// No errors
|
||||
@ -505,13 +505,13 @@ namespace dxvk {
|
||||
if (m_shaders.gs != nullptr) Logger::log(level, str::format(" gs : ", m_shaders.gs ->debugName()));
|
||||
if (m_shaders.fs != nullptr) Logger::log(level, str::format(" fs : ", m_shaders.fs ->debugName()));
|
||||
|
||||
for (uint32_t i = 0; i < state.ilAttributeCount; i++) {
|
||||
const VkVertexInputAttributeDescription& attr = state.ilAttributes[i];
|
||||
Logger::log(level, str::format(" attr ", i, " : location ", attr.location, ", binding ", attr.binding, ", format ", attr.format, ", offset ", attr.offset));
|
||||
for (uint32_t i = 0; i < state.il.attributeCount(); i++) {
|
||||
const auto& attr = state.ilAttributes[i];
|
||||
Logger::log(level, str::format(" attr ", i, " : location ", attr.location(), ", binding ", attr.binding(), ", format ", attr.format(), ", offset ", attr.offset()));
|
||||
}
|
||||
for (uint32_t i = 0; i < state.ilBindingCount; i++) {
|
||||
const VkVertexInputBindingDescription& bind = state.ilBindings[i];
|
||||
Logger::log(level, str::format(" binding ", i, " : binding ", bind.binding, ", stride ", bind.stride, ", rate ", bind.inputRate, ", divisor ", state.ilDivisors[i]));
|
||||
for (uint32_t i = 0; i < state.il.bindingCount(); i++) {
|
||||
const auto& bind = state.ilBindings[i];
|
||||
Logger::log(level, str::format(" binding ", i, " : binding ", bind.binding(), ", stride ", bind.stride(), ", rate ", bind.inputRate(), ", divisor ", bind.divisor()));
|
||||
}
|
||||
|
||||
// TODO log more pipeline state
|
||||
|
@ -51,6 +51,162 @@ namespace dxvk {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Packed input layout metadata
|
||||
*
|
||||
* Stores the number of vertex attributes
|
||||
* and bindings in one byte each.
|
||||
*/
|
||||
class DxvkIlInfo {
|
||||
|
||||
public:
|
||||
|
||||
DxvkIlInfo() = default;
|
||||
|
||||
DxvkIlInfo(
|
||||
uint32_t attributeCount,
|
||||
uint32_t bindingCount)
|
||||
: m_attributeCount(uint8_t(attributeCount)),
|
||||
m_bindingCount (uint8_t(bindingCount)) { }
|
||||
|
||||
uint32_t attributeCount() const {
|
||||
return m_attributeCount;
|
||||
}
|
||||
|
||||
uint32_t bindingCount() const {
|
||||
return m_bindingCount;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
uint8_t m_attributeCount;
|
||||
uint8_t m_bindingCount;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Packed vertex attribute
|
||||
*
|
||||
* Stores a vertex attribute description. Assumes
|
||||
* that all vertex formats have numerical values
|
||||
* of 127 or less (i.e. fit into 7 bits).
|
||||
*/
|
||||
class DxvkIlAttribute {
|
||||
|
||||
public:
|
||||
|
||||
DxvkIlAttribute() = default;
|
||||
|
||||
DxvkIlAttribute(
|
||||
uint32_t location,
|
||||
uint32_t binding,
|
||||
VkFormat format,
|
||||
uint32_t offset)
|
||||
: m_location(uint32_t(location)),
|
||||
m_binding (uint32_t(binding)),
|
||||
m_format (uint32_t(format)),
|
||||
m_offset (uint32_t(offset)),
|
||||
m_reserved(0) { }
|
||||
|
||||
uint32_t location() const {
|
||||
return m_location;
|
||||
}
|
||||
|
||||
uint32_t binding() const {
|
||||
return m_binding;
|
||||
}
|
||||
|
||||
VkFormat format() const {
|
||||
return VkFormat(m_format);
|
||||
}
|
||||
|
||||
uint32_t offset() const {
|
||||
return m_offset;
|
||||
}
|
||||
|
||||
VkVertexInputAttributeDescription description() const {
|
||||
VkVertexInputAttributeDescription result;
|
||||
result.location = m_location;
|
||||
result.binding = m_binding;
|
||||
result.format = VkFormat(m_format);
|
||||
result.offset = m_offset;
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
uint32_t m_location : 5;
|
||||
uint32_t m_binding : 5;
|
||||
uint32_t m_format : 7;
|
||||
uint32_t m_offset : 11;
|
||||
uint32_t m_reserved : 4;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Packed vertex binding
|
||||
*
|
||||
* Stores a vertex binding description,
|
||||
* including the 32-bit divisor.
|
||||
*/
|
||||
class DxvkIlBinding {
|
||||
|
||||
public:
|
||||
|
||||
DxvkIlBinding() = default;
|
||||
|
||||
DxvkIlBinding(
|
||||
uint32_t binding,
|
||||
uint32_t stride,
|
||||
VkVertexInputRate inputRate,
|
||||
uint32_t divisor)
|
||||
: m_binding (uint32_t(binding)),
|
||||
m_stride (uint32_t(stride)),
|
||||
m_inputRate (uint32_t(inputRate)),
|
||||
m_reserved (0),
|
||||
m_divisor (divisor) { }
|
||||
|
||||
uint32_t binding() const {
|
||||
return m_binding;
|
||||
}
|
||||
|
||||
uint32_t stride() const {
|
||||
return m_stride;
|
||||
}
|
||||
|
||||
VkVertexInputRate inputRate() const {
|
||||
return VkVertexInputRate(m_inputRate);
|
||||
}
|
||||
|
||||
uint32_t divisor() const {
|
||||
return m_divisor;
|
||||
}
|
||||
|
||||
VkVertexInputBindingDescription description() const {
|
||||
VkVertexInputBindingDescription result;
|
||||
result.binding = m_binding;
|
||||
result.stride = m_stride;
|
||||
result.inputRate = VkVertexInputRate(m_inputRate);
|
||||
return result;
|
||||
}
|
||||
|
||||
void setStride(uint32_t stride) {
|
||||
m_stride = stride;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
uint32_t m_binding : 5;
|
||||
uint32_t m_stride : 12;
|
||||
uint32_t m_inputRate : 1;
|
||||
uint32_t m_reserved : 14;
|
||||
uint32_t m_divisor;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Packed graphics pipeline state
|
||||
*
|
||||
@ -108,12 +264,7 @@ namespace dxvk {
|
||||
|
||||
DxvkBindingMask bsBindingMask;
|
||||
DxvkIaInfo ia;
|
||||
|
||||
uint32_t ilAttributeCount;
|
||||
uint32_t ilBindingCount;
|
||||
VkVertexInputAttributeDescription ilAttributes[DxvkLimits::MaxNumVertexAttributes];
|
||||
VkVertexInputBindingDescription ilBindings[DxvkLimits::MaxNumVertexBindings];
|
||||
uint32_t ilDivisors[DxvkLimits::MaxNumVertexBindings];
|
||||
DxvkIlInfo il;
|
||||
|
||||
VkBool32 rsDepthClipEnable;
|
||||
VkBool32 rsDepthBiasEnable;
|
||||
@ -141,6 +292,9 @@ namespace dxvk {
|
||||
VkComponentMapping omComponentMapping[MaxNumRenderTargets];
|
||||
|
||||
uint32_t scSpecConstants[MaxNumSpecConstants];
|
||||
|
||||
DxvkIlAttribute ilAttributes [DxvkLimits::MaxNumVertexAttributes];
|
||||
DxvkIlBinding ilBindings [DxvkLimits::MaxNumVertexBindings];
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user