summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/renderer_vulkan/fixed_pipeline_state.cpp52
-rw-r--r--src/video_core/renderer_vulkan/fixed_pipeline_state.h94
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp53
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp6
4 files changed, 84 insertions, 121 deletions
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
index 6b5264c22..07358b0f9 100644
--- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
+++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
@@ -39,24 +39,7 @@ constexpr std::array POLYGON_OFFSET_ENABLE_LUT = {
39 39
40} // Anonymous namespace 40} // Anonymous namespace
41 41
42void FixedPipelineState::VertexInput::Fill(const Maxwell& regs) noexcept { 42void FixedPipelineState::Fill(const Maxwell& regs) {
43 for (std::size_t index = 0; index < Maxwell::NumVertexAttributes; ++index) {
44 const auto& input = regs.vertex_attrib_format[index];
45 auto& attribute = attributes[index];
46 attribute.raw = 0;
47 attribute.enabled.Assign(input.IsConstant() ? 0 : 1);
48 attribute.buffer.Assign(input.buffer);
49 attribute.offset.Assign(input.offset);
50 attribute.type.Assign(static_cast<u32>(input.type.Value()));
51 attribute.size.Assign(static_cast<u32>(input.size.Value()));
52 }
53 for (std::size_t index = 0; index < Maxwell::NumVertexArrays; ++index) {
54 binding_divisors[index] =
55 regs.instanced_arrays.IsInstancingEnabled(index) ? regs.vertex_array[index].divisor : 0;
56 }
57}
58
59void FixedPipelineState::Rasterizer::Fill(const Maxwell& regs) noexcept {
60 const auto& clip = regs.view_volume_clip_control; 43 const auto& clip = regs.view_volume_clip_control;
61 const std::array enabled_lut = {regs.polygon_offset_point_enable, 44 const std::array enabled_lut = {regs.polygon_offset_point_enable,
62 regs.polygon_offset_line_enable, 45 regs.polygon_offset_line_enable,
@@ -76,19 +59,34 @@ void FixedPipelineState::Rasterizer::Fill(const Maxwell& regs) noexcept {
76 logic_op_enable.Assign(regs.logic_op.enable != 0 ? 1 : 0); 59 logic_op_enable.Assign(regs.logic_op.enable != 0 ? 1 : 0);
77 logic_op.Assign(PackLogicOp(regs.logic_op.operation)); 60 logic_op.Assign(PackLogicOp(regs.logic_op.operation));
78 rasterize_enable.Assign(regs.rasterize_enable != 0 ? 1 : 0); 61 rasterize_enable.Assign(regs.rasterize_enable != 0 ? 1 : 0);
62
79 std::memcpy(&point_size, &regs.point_size, sizeof(point_size)); // TODO: C++20 std::bit_cast 63 std::memcpy(&point_size, &regs.point_size, sizeof(point_size)); // TODO: C++20 std::bit_cast
80}
81 64
82void FixedPipelineState::ColorBlending::Fill(const Maxwell& regs) noexcept { 65 for (std::size_t index = 0; index < Maxwell::NumVertexArrays; ++index) {
66 binding_divisors[index] =
67 regs.instanced_arrays.IsInstancingEnabled(index) ? regs.vertex_array[index].divisor : 0;
68 }
69
70 for (std::size_t index = 0; index < Maxwell::NumVertexAttributes; ++index) {
71 const auto& input = regs.vertex_attrib_format[index];
72 auto& attribute = attributes[index];
73 attribute.raw = 0;
74 attribute.enabled.Assign(input.IsConstant() ? 0 : 1);
75 attribute.buffer.Assign(input.buffer);
76 attribute.offset.Assign(input.offset);
77 attribute.type.Assign(static_cast<u32>(input.type.Value()));
78 attribute.size.Assign(static_cast<u32>(input.size.Value()));
79 }
80
83 for (std::size_t index = 0; index < std::size(attachments); ++index) { 81 for (std::size_t index = 0; index < std::size(attachments); ++index) {
84 attachments[index].Fill(regs, index); 82 attachments[index].Fill(regs, index);
85 } 83 }
86}
87 84
88void FixedPipelineState::ViewportSwizzles::Fill(const Maxwell& regs) noexcept {
89 const auto& transform = regs.viewport_transform; 85 const auto& transform = regs.viewport_transform;
90 std::transform(transform.begin(), transform.end(), swizzles.begin(), 86 std::transform(transform.begin(), transform.end(), viewport_swizzles.begin(),
91 [](const auto& viewport) { return static_cast<u16>(viewport.swizzle.raw); }); 87 [](const auto& viewport) { return static_cast<u16>(viewport.swizzle.raw); });
88
89 dynamic_state.Fill(regs);
92} 90}
93 91
94void FixedPipelineState::BlendingAttachment::Fill(const Maxwell& regs, std::size_t index) { 92void FixedPipelineState::BlendingAttachment::Fill(const Maxwell& regs, std::size_t index) {
@@ -174,14 +172,6 @@ void FixedPipelineState::DynamicState::Fill(const Maxwell& regs) {
174 } 172 }
175} 173}
176 174
177void FixedPipelineState::Fill(const Maxwell& regs) {
178 vertex_input.Fill(regs);
179 rasterizer.Fill(regs);
180 color_blending.Fill(regs);
181 viewport_swizzles.Fill(regs);
182 dynamic_state.Fill(regs);
183}
184
185std::size_t FixedPipelineState::Hash() const noexcept { 175std::size_t FixedPipelineState::Hash() const noexcept {
186 const u64 hash = Common::CityHash64(reinterpret_cast<const char*>(this), sizeof *this); 176 const u64 hash = Common::CityHash64(reinterpret_cast<const char*>(this), sizeof *this);
187 return static_cast<std::size_t>(hash); 177 return static_cast<std::size_t>(hash);
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.h b/src/video_core/renderer_vulkan/fixed_pipeline_state.h
index 54474fee7..09d05702d 100644
--- a/src/video_core/renderer_vulkan/fixed_pipeline_state.h
+++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.h
@@ -89,63 +89,21 @@ struct FixedPipelineState {
89 } 89 }
90 }; 90 };
91 91
92 struct VertexInput { 92 union VertexAttribute {
93 union Attribute { 93 u32 raw;
94 u32 raw; 94 BitField<0, 1, u32> enabled;
95 BitField<0, 1, u32> enabled; 95 BitField<1, 5, u32> buffer;
96 BitField<1, 5, u32> buffer; 96 BitField<6, 14, u32> offset;
97 BitField<6, 14, u32> offset; 97 BitField<20, 3, u32> type;
98 BitField<20, 3, u32> type; 98 BitField<23, 6, u32> size;
99 BitField<23, 6, u32> size; 99
100 100 constexpr Maxwell::VertexAttribute::Type Type() const noexcept {
101 constexpr Maxwell::VertexAttribute::Type Type() const noexcept { 101 return static_cast<Maxwell::VertexAttribute::Type>(type.Value());
102 return static_cast<Maxwell::VertexAttribute::Type>(type.Value()); 102 }
103 }
104
105 constexpr Maxwell::VertexAttribute::Size Size() const noexcept {
106 return static_cast<Maxwell::VertexAttribute::Size>(size.Value());
107 }
108 };
109
110 std::array<u32, Maxwell::NumVertexArrays> binding_divisors;
111 std::array<Attribute, Maxwell::NumVertexAttributes> attributes;
112
113 void Fill(const Maxwell& regs) noexcept;
114 };
115
116 struct Rasterizer {
117 union {
118 u32 raw;
119 BitField<0, 1, u32> primitive_restart_enable;
120 BitField<1, 1, u32> depth_bias_enable;
121 BitField<2, 1, u32> depth_clamp_disabled;
122 BitField<3, 1, u32> ndc_minus_one_to_one;
123 BitField<4, 2, u32> polygon_mode;
124 BitField<6, 5, u32> patch_control_points_minus_one;
125 BitField<11, 2, u32> tessellation_primitive;
126 BitField<13, 2, u32> tessellation_spacing;
127 BitField<15, 1, u32> tessellation_clockwise;
128 BitField<16, 1, u32> logic_op_enable;
129 BitField<17, 4, u32> logic_op;
130 BitField<21, 1, u32> rasterize_enable;
131 };
132
133 // TODO(Rodrigo): Move this to push constants
134 u32 point_size;
135
136 void Fill(const Maxwell& regs) noexcept;
137 };
138
139 struct ColorBlending {
140 std::array<BlendingAttachment, Maxwell::NumRenderTargets> attachments;
141
142 void Fill(const Maxwell& regs) noexcept;
143 };
144
145 struct ViewportSwizzles {
146 std::array<u16, Maxwell::NumViewports> swizzles;
147 103
148 void Fill(const Maxwell& regs) noexcept; 104 constexpr Maxwell::VertexAttribute::Size Size() const noexcept {
105 return static_cast<Maxwell::VertexAttribute::Size>(size.Value());
106 }
149 }; 107 };
150 108
151 template <std::size_t Position> 109 template <std::size_t Position>
@@ -217,10 +175,26 @@ struct FixedPipelineState {
217 } 175 }
218 }; 176 };
219 177
220 VertexInput vertex_input; 178 union {
221 Rasterizer rasterizer; 179 u32 raw;
222 ColorBlending color_blending; 180 BitField<0, 1, u32> primitive_restart_enable;
223 ViewportSwizzles viewport_swizzles; 181 BitField<1, 1, u32> depth_bias_enable;
182 BitField<2, 1, u32> depth_clamp_disabled;
183 BitField<3, 1, u32> ndc_minus_one_to_one;
184 BitField<4, 2, u32> polygon_mode;
185 BitField<6, 5, u32> patch_control_points_minus_one;
186 BitField<11, 2, u32> tessellation_primitive;
187 BitField<13, 2, u32> tessellation_spacing;
188 BitField<15, 1, u32> tessellation_clockwise;
189 BitField<16, 1, u32> logic_op_enable;
190 BitField<17, 4, u32> logic_op;
191 BitField<21, 1, u32> rasterize_enable;
192 };
193 u32 point_size;
194 std::array<u32, Maxwell::NumVertexArrays> binding_divisors;
195 std::array<VertexAttribute, Maxwell::NumVertexAttributes> attributes;
196 std::array<BlendingAttachment, Maxwell::NumRenderTargets> attachments;
197 std::array<u16, Maxwell::NumViewports> viewport_swizzles;
224 DynamicState dynamic_state; 198 DynamicState dynamic_state;
225 199
226 void Fill(const Maxwell& regs); 200 void Fill(const Maxwell& regs);
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index 739801f5d..15d9ac3b0 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -176,20 +176,18 @@ std::vector<vk::ShaderModule> VKGraphicsPipeline::CreateShaderModules(
176 176
177vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpass_params, 177vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpass_params,
178 const SPIRVProgram& program) const { 178 const SPIRVProgram& program) const {
179 const auto& vi = fixed_state.vertex_input; 179 const auto& state = fixed_state;
180 const auto& cd = fixed_state.color_blending; 180 const auto& dynamic = fixed_state.dynamic_state;
181 const auto& rs = fixed_state.rasterizer; 181 const auto& viewport_swizzles = fixed_state.viewport_swizzles;
182 const auto& ds = fixed_state.dynamic_state;
183 const auto& viewport_swizzles = fixed_state.viewport_swizzles.swizzles;
184 182
185 std::vector<VkVertexInputBindingDescription> vertex_bindings; 183 std::vector<VkVertexInputBindingDescription> vertex_bindings;
186 std::vector<VkVertexInputBindingDivisorDescriptionEXT> vertex_binding_divisors; 184 std::vector<VkVertexInputBindingDivisorDescriptionEXT> vertex_binding_divisors;
187 for (std::size_t index = 0; index < Maxwell::NumVertexArrays; ++index) { 185 for (std::size_t index = 0; index < Maxwell::NumVertexArrays; ++index) {
188 const auto& binding = ds.vertex_bindings[index]; 186 const auto& binding = dynamic.vertex_bindings[index];
189 if (!binding.enabled) { 187 if (!binding.enabled) {
190 continue; 188 continue;
191 } 189 }
192 const bool instanced = vi.binding_divisors[index] != 0; 190 const bool instanced = state.binding_divisors[index] != 0;
193 const auto rate = instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX; 191 const auto rate = instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
194 192
195 auto& vertex_binding = vertex_bindings.emplace_back(); 193 auto& vertex_binding = vertex_bindings.emplace_back();
@@ -200,14 +198,14 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
200 if (instanced) { 198 if (instanced) {
201 auto& binding_divisor = vertex_binding_divisors.emplace_back(); 199 auto& binding_divisor = vertex_binding_divisors.emplace_back();
202 binding_divisor.binding = static_cast<u32>(index); 200 binding_divisor.binding = static_cast<u32>(index);
203 binding_divisor.divisor = vi.binding_divisors[index]; 201 binding_divisor.divisor = state.binding_divisors[index];
204 } 202 }
205 } 203 }
206 204
207 std::vector<VkVertexInputAttributeDescription> vertex_attributes; 205 std::vector<VkVertexInputAttributeDescription> vertex_attributes;
208 const auto& input_attributes = program[0]->entries.attributes; 206 const auto& input_attributes = program[0]->entries.attributes;
209 for (std::size_t index = 0; index < std::size(vi.attributes); ++index) { 207 for (std::size_t index = 0; index < state.attributes.size(); ++index) {
210 const auto& attribute = vi.attributes[index]; 208 const auto& attribute = state.attributes[index];
211 if (!attribute.enabled) { 209 if (!attribute.enabled) {
212 continue; 210 continue;
213 } 211 }
@@ -244,15 +242,15 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
244 input_assembly_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; 242 input_assembly_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
245 input_assembly_ci.pNext = nullptr; 243 input_assembly_ci.pNext = nullptr;
246 input_assembly_ci.flags = 0; 244 input_assembly_ci.flags = 0;
247 input_assembly_ci.topology = MaxwellToVK::PrimitiveTopology(device, ds.Topology()); 245 input_assembly_ci.topology = MaxwellToVK::PrimitiveTopology(device, dynamic.Topology());
248 input_assembly_ci.primitiveRestartEnable = 246 input_assembly_ci.primitiveRestartEnable =
249 rs.primitive_restart_enable != 0 && SupportsPrimitiveRestart(input_assembly_ci.topology); 247 state.primitive_restart_enable != 0 && SupportsPrimitiveRestart(input_assembly_ci.topology);
250 248
251 VkPipelineTessellationStateCreateInfo tessellation_ci; 249 VkPipelineTessellationStateCreateInfo tessellation_ci;
252 tessellation_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO; 250 tessellation_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
253 tessellation_ci.pNext = nullptr; 251 tessellation_ci.pNext = nullptr;
254 tessellation_ci.flags = 0; 252 tessellation_ci.flags = 0;
255 tessellation_ci.patchControlPoints = rs.patch_control_points_minus_one.Value() + 1; 253 tessellation_ci.patchControlPoints = state.patch_control_points_minus_one.Value() + 1;
256 254
257 VkPipelineViewportStateCreateInfo viewport_ci; 255 VkPipelineViewportStateCreateInfo viewport_ci;
258 viewport_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; 256 viewport_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
@@ -280,13 +278,13 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
280 rasterization_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; 278 rasterization_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
281 rasterization_ci.pNext = nullptr; 279 rasterization_ci.pNext = nullptr;
282 rasterization_ci.flags = 0; 280 rasterization_ci.flags = 0;
283 rasterization_ci.depthClampEnable = rs.depth_clamp_disabled == 0 ? VK_TRUE : VK_FALSE; 281 rasterization_ci.depthClampEnable = state.depth_clamp_disabled == 0 ? VK_TRUE : VK_FALSE;
284 rasterization_ci.rasterizerDiscardEnable = rs.rasterize_enable == 0 ? VK_TRUE : VK_FALSE; 282 rasterization_ci.rasterizerDiscardEnable = state.rasterize_enable == 0 ? VK_TRUE : VK_FALSE;
285 rasterization_ci.polygonMode = VK_POLYGON_MODE_FILL; 283 rasterization_ci.polygonMode = VK_POLYGON_MODE_FILL;
286 rasterization_ci.cullMode = 284 rasterization_ci.cullMode =
287 ds.cull_enable ? MaxwellToVK::CullFace(ds.CullFace()) : VK_CULL_MODE_NONE; 285 dynamic.cull_enable ? MaxwellToVK::CullFace(dynamic.CullFace()) : VK_CULL_MODE_NONE;
288 rasterization_ci.frontFace = MaxwellToVK::FrontFace(ds.FrontFace()); 286 rasterization_ci.frontFace = MaxwellToVK::FrontFace(dynamic.FrontFace());
289 rasterization_ci.depthBiasEnable = rs.depth_bias_enable; 287 rasterization_ci.depthBiasEnable = state.depth_bias_enable;
290 rasterization_ci.depthBiasConstantFactor = 0.0f; 288 rasterization_ci.depthBiasConstantFactor = 0.0f;
291 rasterization_ci.depthBiasClamp = 0.0f; 289 rasterization_ci.depthBiasClamp = 0.0f;
292 rasterization_ci.depthBiasSlopeFactor = 0.0f; 290 rasterization_ci.depthBiasSlopeFactor = 0.0f;
@@ -307,14 +305,15 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
307 depth_stencil_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; 305 depth_stencil_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
308 depth_stencil_ci.pNext = nullptr; 306 depth_stencil_ci.pNext = nullptr;
309 depth_stencil_ci.flags = 0; 307 depth_stencil_ci.flags = 0;
310 depth_stencil_ci.depthTestEnable = ds.depth_test_enable; 308 depth_stencil_ci.depthTestEnable = dynamic.depth_test_enable;
311 depth_stencil_ci.depthWriteEnable = ds.depth_write_enable; 309 depth_stencil_ci.depthWriteEnable = dynamic.depth_write_enable;
312 depth_stencil_ci.depthCompareOp = 310 depth_stencil_ci.depthCompareOp = dynamic.depth_test_enable
313 ds.depth_test_enable ? MaxwellToVK::ComparisonOp(ds.DepthTestFunc()) : VK_COMPARE_OP_ALWAYS; 311 ? MaxwellToVK::ComparisonOp(dynamic.DepthTestFunc())
314 depth_stencil_ci.depthBoundsTestEnable = ds.depth_bounds_enable; 312 : VK_COMPARE_OP_ALWAYS;
315 depth_stencil_ci.stencilTestEnable = ds.stencil_enable; 313 depth_stencil_ci.depthBoundsTestEnable = dynamic.depth_bounds_enable;
316 depth_stencil_ci.front = GetStencilFaceState(ds.front); 314 depth_stencil_ci.stencilTestEnable = dynamic.stencil_enable;
317 depth_stencil_ci.back = GetStencilFaceState(ds.back); 315 depth_stencil_ci.front = GetStencilFaceState(dynamic.front);
316 depth_stencil_ci.back = GetStencilFaceState(dynamic.back);
318 depth_stencil_ci.minDepthBounds = 0.0f; 317 depth_stencil_ci.minDepthBounds = 0.0f;
319 depth_stencil_ci.maxDepthBounds = 0.0f; 318 depth_stencil_ci.maxDepthBounds = 0.0f;
320 319
@@ -324,7 +323,7 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
324 static constexpr std::array COMPONENT_TABLE = { 323 static constexpr std::array COMPONENT_TABLE = {
325 VK_COLOR_COMPONENT_R_BIT, VK_COLOR_COMPONENT_G_BIT, VK_COLOR_COMPONENT_B_BIT, 324 VK_COLOR_COMPONENT_R_BIT, VK_COLOR_COMPONENT_G_BIT, VK_COLOR_COMPONENT_B_BIT,
326 VK_COLOR_COMPONENT_A_BIT}; 325 VK_COLOR_COMPONENT_A_BIT};
327 const auto& blend = cd.attachments[index]; 326 const auto& blend = state.attachments[index];
328 327
329 VkColorComponentFlags color_components = 0; 328 VkColorComponentFlags color_components = 0;
330 for (std::size_t i = 0; i < COMPONENT_TABLE.size(); ++i) { 329 for (std::size_t i = 0; i < COMPONENT_TABLE.size(); ++i) {
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index 9fcb46f8a..e684c17a6 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -314,16 +314,16 @@ VKPipelineCache::DecompileShaders(const GraphicsPipelineCacheKey& key) {
314 Specialization specialization; 314 Specialization specialization;
315 if (fixed_state.dynamic_state.Topology() == Maxwell::PrimitiveTopology::Points) { 315 if (fixed_state.dynamic_state.Topology() == Maxwell::PrimitiveTopology::Points) {
316 float point_size; 316 float point_size;
317 std::memcpy(&point_size, &fixed_state.rasterizer.point_size, sizeof(float)); 317 std::memcpy(&point_size, &fixed_state.point_size, sizeof(float));
318 specialization.point_size = point_size; 318 specialization.point_size = point_size;
319 ASSERT(point_size != 0.0f); 319 ASSERT(point_size != 0.0f);
320 } 320 }
321 for (std::size_t i = 0; i < Maxwell::NumVertexAttributes; ++i) { 321 for (std::size_t i = 0; i < Maxwell::NumVertexAttributes; ++i) {
322 const auto& attribute = fixed_state.vertex_input.attributes[i]; 322 const auto& attribute = fixed_state.attributes[i];
323 specialization.enabled_attributes[i] = attribute.enabled.Value() != 0; 323 specialization.enabled_attributes[i] = attribute.enabled.Value() != 0;
324 specialization.attribute_types[i] = attribute.Type(); 324 specialization.attribute_types[i] = attribute.Type();
325 } 325 }
326 specialization.ndc_minus_one_to_one = fixed_state.rasterizer.ndc_minus_one_to_one; 326 specialization.ndc_minus_one_to_one = fixed_state.ndc_minus_one_to_one;
327 327
328 SPIRVProgram program; 328 SPIRVProgram program;
329 std::vector<VkDescriptorSetLayoutBinding> bindings; 329 std::vector<VkDescriptorSetLayoutBinding> bindings;