1
0
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:
Philip Rebohle 2019-10-07 11:51:57 +02:00
parent c0ae4e38eb
commit a5ab88d8f2
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
3 changed files with 202 additions and 52 deletions

View File

@ -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());
}

View File

@ -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

View File

@ -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];
};
}