summaryrefslogtreecommitdiff
path: root/src/video_core
diff options
context:
space:
mode:
authorGravatar FengChen2022-09-01 22:05:11 +0800
committerGravatar FengChen2022-09-20 11:55:43 +0800
commit9a95c7fa14bdfc14aacea92896c8ae8533918fe8 (patch)
tree3beb2289136a59134195d35e37d4b56b294a3081 /src/video_core
parentMerge pull request #8841 from zhaobot/tx-update-20220901035349 (diff)
downloadyuzu-9a95c7fa14bdfc14aacea92896c8ae8533918fe8.tar.gz
yuzu-9a95c7fa14bdfc14aacea92896c8ae8533918fe8.tar.xz
yuzu-9a95c7fa14bdfc14aacea92896c8ae8533918fe8.zip
video_core: Generate mipmap texture by drawing
Diffstat (limited to 'src/video_core')
-rw-r--r--src/video_core/renderer_opengl/gl_graphics_pipeline.cpp11
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp10
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp2
-rw-r--r--src/video_core/renderer_vulkan/pipeline_helper.h10
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp24
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.h4
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp16
-rw-r--r--src/video_core/shader_environment.cpp17
-rw-r--r--src/video_core/shader_environment.h9
9 files changed, 96 insertions, 7 deletions
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
index 67eae369d..c297f7121 100644
--- a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
+++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
@@ -502,6 +502,17 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
502 float_image_scaling_mask, down_factor, 0.0f); 502 float_image_scaling_mask, down_factor, 0.0f);
503 } 503 }
504 } 504 }
505 if (info.uses_render_area) {
506 const auto render_area_width(static_cast<GLfloat>(regs.render_area.width));
507 const auto render_area_height(static_cast<GLfloat>(regs.render_area.height));
508 if (use_assembly) {
509 glProgramLocalParameter4fARB(AssemblyStage(stage), 1, render_area_width,
510 render_area_height, 0.0f, 0.0f);
511 } else {
512 glProgramUniform4f(source_programs[stage].handle, 1, render_area_width,
513 render_area_height, 0.0f, 0.0f);
514 }
515 }
505 }}; 516 }};
506 if constexpr (Spec::enabled_stages[0]) { 517 if constexpr (Spec::enabled_stages[0]) {
507 prepare_stage(0); 518 prepare_stage(0);
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index a0d048b0b..f018333af 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -622,6 +622,16 @@ void RasterizerOpenGL::SyncViewport() {
622 } 622 }
623 flags[Dirty::Viewport0 + index] = false; 623 flags[Dirty::Viewport0 + index] = false;
624 624
625 if (!regs.viewport_transform_enabled) {
626 const auto x = static_cast<GLfloat>(regs.render_area.x);
627 const auto y = static_cast<GLfloat>(regs.render_area.y);
628 const auto width = static_cast<GLfloat>(regs.render_area.width);
629 const auto height = static_cast<GLfloat>(regs.render_area.height);
630 glViewportIndexedf(static_cast<GLuint>(index), x, y, width != 0.0f ? width : 1.0f,
631 height != 0.0f ? height : 1.0f);
632 continue;
633 }
634
625 const auto& src = regs.viewport_transform[index]; 635 const auto& src = regs.viewport_transform[index];
626 GLfloat x = conv(src.translate_x - src.scale_x); 636 GLfloat x = conv(src.translate_x - src.scale_x);
627 GLfloat y = conv(src.translate_y - src.scale_y); 637 GLfloat y = conv(src.translate_y - src.scale_y);
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index 1ad56d9e7..7e76f679f 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -49,7 +49,7 @@ using VideoCommon::LoadPipelines;
49using VideoCommon::SerializePipeline; 49using VideoCommon::SerializePipeline;
50using Context = ShaderContext::Context; 50using Context = ShaderContext::Context;
51 51
52constexpr u32 CACHE_VERSION = 5; 52constexpr u32 CACHE_VERSION = 7;
53 53
54template <typename Container> 54template <typename Container>
55auto MakeSpan(Container& container) { 55auto MakeSpan(Container& container) {
diff --git a/src/video_core/renderer_vulkan/pipeline_helper.h b/src/video_core/renderer_vulkan/pipeline_helper.h
index b24f3424a..b7843e995 100644
--- a/src/video_core/renderer_vulkan/pipeline_helper.h
+++ b/src/video_core/renderer_vulkan/pipeline_helper.h
@@ -68,13 +68,15 @@ public:
68 } 68 }
69 69
70 vk::PipelineLayout CreatePipelineLayout(VkDescriptorSetLayout descriptor_set_layout) const { 70 vk::PipelineLayout CreatePipelineLayout(VkDescriptorSetLayout descriptor_set_layout) const {
71 using Shader::Backend::SPIRV::RenderAreaLayout;
71 using Shader::Backend::SPIRV::RescalingLayout; 72 using Shader::Backend::SPIRV::RescalingLayout;
72 const u32 size_offset = is_compute ? sizeof(RescalingLayout::down_factor) : 0u; 73 const u32 size_offset = is_compute ? sizeof(RescalingLayout::down_factor) : 0u;
73 const VkPushConstantRange range{ 74 const VkPushConstantRange range{
74 .stageFlags = static_cast<VkShaderStageFlags>( 75 .stageFlags = static_cast<VkShaderStageFlags>(
75 is_compute ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_ALL_GRAPHICS), 76 is_compute ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_ALL_GRAPHICS),
76 .offset = 0, 77 .offset = 0,
77 .size = static_cast<u32>(sizeof(RescalingLayout)) - size_offset, 78 .size = static_cast<u32>(sizeof(RescalingLayout)) - size_offset +
79 static_cast<u32>(sizeof(RenderAreaLayout)),
78 }; 80 };
79 return device->GetLogical().CreatePipelineLayout({ 81 return device->GetLogical().CreatePipelineLayout({
80 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, 82 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
@@ -167,6 +169,12 @@ private:
167 u32 image_bit{1u}; 169 u32 image_bit{1u};
168}; 170};
169 171
172class RenderAreaPushConstant {
173public:
174 bool uses_render_area{};
175 std::array<f32, 4> words{};
176};
177
170inline void PushImageDescriptors(TextureCache& texture_cache, 178inline void PushImageDescriptors(TextureCache& texture_cache,
171 UpdateDescriptorQueue& update_descriptor_queue, 179 UpdateDescriptorQueue& update_descriptor_queue,
172 const Shader::Info& info, RescalingPushConstant& rescaling, 180 const Shader::Info& info, RescalingPushConstant& rescaling,
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index 5aca8f038..7eb623a7c 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -31,6 +31,7 @@ namespace {
31using boost::container::small_vector; 31using boost::container::small_vector;
32using boost::container::static_vector; 32using boost::container::static_vector;
33using Shader::ImageBufferDescriptor; 33using Shader::ImageBufferDescriptor;
34using Shader::Backend::SPIRV::RENDERAREA_LAYOUT_OFFSET;
34using Shader::Backend::SPIRV::RESCALING_LAYOUT_DOWN_FACTOR_OFFSET; 35using Shader::Backend::SPIRV::RESCALING_LAYOUT_DOWN_FACTOR_OFFSET;
35using Shader::Backend::SPIRV::RESCALING_LAYOUT_WORDS_OFFSET; 36using Shader::Backend::SPIRV::RESCALING_LAYOUT_WORDS_OFFSET;
36using Tegra::Texture::TexturePair; 37using Tegra::Texture::TexturePair;
@@ -433,12 +434,19 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
433 update_descriptor_queue.Acquire(); 434 update_descriptor_queue.Acquire();
434 435
435 RescalingPushConstant rescaling; 436 RescalingPushConstant rescaling;
437 RenderAreaPushConstant render_area;
436 const VkSampler* samplers_it{samplers.data()}; 438 const VkSampler* samplers_it{samplers.data()};
437 const VideoCommon::ImageViewInOut* views_it{views.data()}; 439 const VideoCommon::ImageViewInOut* views_it{views.data()};
438 const auto prepare_stage{[&](size_t stage) LAMBDA_FORCEINLINE { 440 const auto prepare_stage{[&](size_t stage) LAMBDA_FORCEINLINE {
439 buffer_cache.BindHostStageBuffers(stage); 441 buffer_cache.BindHostStageBuffers(stage);
440 PushImageDescriptors(texture_cache, update_descriptor_queue, stage_infos[stage], rescaling, 442 PushImageDescriptors(texture_cache, update_descriptor_queue, stage_infos[stage], rescaling,
441 samplers_it, views_it); 443 samplers_it, views_it);
444 const auto& info{stage_infos[0]};
445 if (info.uses_render_area) {
446 render_area.uses_render_area = true;
447 render_area.words = {static_cast<float>(regs.render_area.width),
448 static_cast<float>(regs.render_area.height)};
449 }
442 }}; 450 }};
443 if constexpr (Spec::enabled_stages[0]) { 451 if constexpr (Spec::enabled_stages[0]) {
444 prepare_stage(0); 452 prepare_stage(0);
@@ -455,10 +463,11 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
455 if constexpr (Spec::enabled_stages[4]) { 463 if constexpr (Spec::enabled_stages[4]) {
456 prepare_stage(4); 464 prepare_stage(4);
457 } 465 }
458 ConfigureDraw(rescaling); 466 ConfigureDraw(rescaling, render_area);
459} 467}
460 468
461void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling) { 469void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling,
470 const RenderAreaPushConstant& render_are) {
462 texture_cache.UpdateRenderTargets(false); 471 texture_cache.UpdateRenderTargets(false);
463 scheduler.RequestRenderpass(texture_cache.GetFramebuffer()); 472 scheduler.RequestRenderpass(texture_cache.GetFramebuffer());
464 473
@@ -474,7 +483,9 @@ void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling) {
474 const bool bind_pipeline{scheduler.UpdateGraphicsPipeline(this)}; 483 const bool bind_pipeline{scheduler.UpdateGraphicsPipeline(this)};
475 const void* const descriptor_data{update_descriptor_queue.UpdateData()}; 484 const void* const descriptor_data{update_descriptor_queue.UpdateData()};
476 scheduler.Record([this, descriptor_data, bind_pipeline, rescaling_data = rescaling.Data(), 485 scheduler.Record([this, descriptor_data, bind_pipeline, rescaling_data = rescaling.Data(),
477 is_rescaling, update_rescaling](vk::CommandBuffer cmdbuf) { 486 is_rescaling, update_rescaling,
487 uses_render_area = render_are.uses_render_area,
488 render_area_data = render_are.words](vk::CommandBuffer cmdbuf) {
478 if (bind_pipeline) { 489 if (bind_pipeline) {
479 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); 490 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
480 } 491 }
@@ -483,11 +494,16 @@ void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling) {
483 rescaling_data.data()); 494 rescaling_data.data());
484 if (update_rescaling) { 495 if (update_rescaling) {
485 const f32 config_down_factor{Settings::values.resolution_info.down_factor}; 496 const f32 config_down_factor{Settings::values.resolution_info.down_factor};
486 const f32 scale_down_factor{is_rescaling ? config_down_factor : 1.0f}; 497 const f32 scale_down_factor{is_rescaling ? config_down_factor : 2.0f};
487 cmdbuf.PushConstants(*pipeline_layout, VK_SHADER_STAGE_ALL_GRAPHICS, 498 cmdbuf.PushConstants(*pipeline_layout, VK_SHADER_STAGE_ALL_GRAPHICS,
488 RESCALING_LAYOUT_DOWN_FACTOR_OFFSET, sizeof(scale_down_factor), 499 RESCALING_LAYOUT_DOWN_FACTOR_OFFSET, sizeof(scale_down_factor),
489 &scale_down_factor); 500 &scale_down_factor);
490 } 501 }
502 if (uses_render_area) {
503 cmdbuf.PushConstants(*pipeline_layout, VK_SHADER_STAGE_ALL_GRAPHICS,
504 RENDERAREA_LAYOUT_OFFSET, sizeof(render_area_data),
505 &render_area_data);
506 }
491 if (!descriptor_set_layout) { 507 if (!descriptor_set_layout) {
492 return; 508 return;
493 } 509 }
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
index e8949a9ab..8842f62d7 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
@@ -62,6 +62,7 @@ class Device;
62class PipelineStatistics; 62class PipelineStatistics;
63class RenderPassCache; 63class RenderPassCache;
64class RescalingPushConstant; 64class RescalingPushConstant;
65class RenderAreaPushConstant;
65class Scheduler; 66class Scheduler;
66class UpdateDescriptorQueue; 67class UpdateDescriptorQueue;
67 68
@@ -113,7 +114,8 @@ private:
113 template <typename Spec> 114 template <typename Spec>
114 void ConfigureImpl(bool is_indexed); 115 void ConfigureImpl(bool is_indexed);
115 116
116 void ConfigureDraw(const RescalingPushConstant& rescaling); 117 void ConfigureDraw(const RescalingPushConstant& rescaling,
118 const RenderAreaPushConstant& render_are);
117 119
118 void MakePipeline(VkRenderPass render_pass); 120 void MakePipeline(VkRenderPass render_pass);
119 121
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 7e40c2df1..bf9f825f4 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -682,6 +682,22 @@ void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& reg
682 if (!state_tracker.TouchViewports()) { 682 if (!state_tracker.TouchViewports()) {
683 return; 683 return;
684 } 684 }
685 if (!regs.viewport_transform_enabled) {
686 const auto x = static_cast<float>(regs.render_area.x);
687 const auto y = static_cast<float>(regs.render_area.y);
688 const auto width = static_cast<float>(regs.render_area.width);
689 const auto height = static_cast<float>(regs.render_area.height);
690 VkViewport viewport{
691 .x = x,
692 .y = y,
693 .width = width != 0.0f ? width : 1.0f,
694 .height = height != 0.0f ? height : 1.0f,
695 .minDepth = 0.0f,
696 .maxDepth = 1.0f,
697 };
698 scheduler.Record([viewport](vk::CommandBuffer cmdbuf) { cmdbuf.SetViewport(0, viewport); });
699 return;
700 }
685 const bool is_rescaling{texture_cache.IsRescaling()}; 701 const bool is_rescaling{texture_cache.IsRescaling()};
686 const float scale = is_rescaling ? Settings::values.resolution_info.up_factor : 1.0f; 702 const float scale = is_rescaling ? Settings::values.resolution_info.up_factor : 1.0f;
687 const std::array viewports{ 703 const std::array viewports{
diff --git a/src/video_core/shader_environment.cpp b/src/video_core/shader_environment.cpp
index 808d88eec..3ead06dd6 100644
--- a/src/video_core/shader_environment.cpp
+++ b/src/video_core/shader_environment.cpp
@@ -191,6 +191,8 @@ void GenericEnvironment::Serialize(std::ofstream& file) const {
191 .write(reinterpret_cast<const char*>(&start_address), sizeof(start_address)) 191 .write(reinterpret_cast<const char*>(&start_address), sizeof(start_address))
192 .write(reinterpret_cast<const char*>(&cached_lowest), sizeof(cached_lowest)) 192 .write(reinterpret_cast<const char*>(&cached_lowest), sizeof(cached_lowest))
193 .write(reinterpret_cast<const char*>(&cached_highest), sizeof(cached_highest)) 193 .write(reinterpret_cast<const char*>(&cached_highest), sizeof(cached_highest))
194 .write(reinterpret_cast<const char*>(&viewport_transform_state),
195 sizeof(viewport_transform_state))
194 .write(reinterpret_cast<const char*>(&stage), sizeof(stage)) 196 .write(reinterpret_cast<const char*>(&stage), sizeof(stage))
195 .write(reinterpret_cast<const char*>(code.data()), code_size); 197 .write(reinterpret_cast<const char*>(code.data()), code_size);
196 for (const auto& [key, type] : texture_types) { 198 for (const auto& [key, type] : texture_types) {
@@ -311,6 +313,12 @@ Shader::TextureType GraphicsEnvironment::ReadTextureType(u32 handle) {
311 return ReadTextureTypeImpl(regs.tic.Address(), regs.tic.limit, via_header_index, handle); 313 return ReadTextureTypeImpl(regs.tic.Address(), regs.tic.limit, via_header_index, handle);
312} 314}
313 315
316u32 GraphicsEnvironment::ReadViewportTransformState() {
317 const auto& regs{maxwell3d->regs};
318 viewport_transform_state = regs.viewport_transform_enabled;
319 return viewport_transform_state;
320}
321
314ComputeEnvironment::ComputeEnvironment(Tegra::Engines::KeplerCompute& kepler_compute_, 322ComputeEnvironment::ComputeEnvironment(Tegra::Engines::KeplerCompute& kepler_compute_,
315 Tegra::MemoryManager& gpu_memory_, GPUVAddr program_base_, 323 Tegra::MemoryManager& gpu_memory_, GPUVAddr program_base_,
316 u32 start_address_) 324 u32 start_address_)
@@ -342,6 +350,10 @@ Shader::TextureType ComputeEnvironment::ReadTextureType(u32 handle) {
342 return ReadTextureTypeImpl(regs.tic.Address(), regs.tic.limit, qmd.linked_tsc != 0, handle); 350 return ReadTextureTypeImpl(regs.tic.Address(), regs.tic.limit, qmd.linked_tsc != 0, handle);
343} 351}
344 352
353u32 ComputeEnvironment::ReadViewportTransformState() {
354 return viewport_transform_state;
355}
356
345void FileEnvironment::Deserialize(std::ifstream& file) { 357void FileEnvironment::Deserialize(std::ifstream& file) {
346 u64 code_size{}; 358 u64 code_size{};
347 u64 num_texture_types{}; 359 u64 num_texture_types{};
@@ -354,6 +366,7 @@ void FileEnvironment::Deserialize(std::ifstream& file) {
354 .read(reinterpret_cast<char*>(&start_address), sizeof(start_address)) 366 .read(reinterpret_cast<char*>(&start_address), sizeof(start_address))
355 .read(reinterpret_cast<char*>(&read_lowest), sizeof(read_lowest)) 367 .read(reinterpret_cast<char*>(&read_lowest), sizeof(read_lowest))
356 .read(reinterpret_cast<char*>(&read_highest), sizeof(read_highest)) 368 .read(reinterpret_cast<char*>(&read_highest), sizeof(read_highest))
369 .read(reinterpret_cast<char*>(&viewport_transform_state), sizeof(viewport_transform_state))
357 .read(reinterpret_cast<char*>(&stage), sizeof(stage)); 370 .read(reinterpret_cast<char*>(&stage), sizeof(stage));
358 code = std::make_unique<u64[]>(Common::DivCeil(code_size, sizeof(u64))); 371 code = std::make_unique<u64[]>(Common::DivCeil(code_size, sizeof(u64)));
359 file.read(reinterpret_cast<char*>(code.get()), code_size); 372 file.read(reinterpret_cast<char*>(code.get()), code_size);
@@ -411,6 +424,10 @@ Shader::TextureType FileEnvironment::ReadTextureType(u32 handle) {
411 return it->second; 424 return it->second;
412} 425}
413 426
427u32 FileEnvironment::ReadViewportTransformState() {
428 return viewport_transform_state;
429}
430
414u32 FileEnvironment::LocalMemorySize() const { 431u32 FileEnvironment::LocalMemorySize() const {
415 return local_memory_size; 432 return local_memory_size;
416} 433}
diff --git a/src/video_core/shader_environment.h b/src/video_core/shader_environment.h
index 5a145f33a..a0659fd7c 100644
--- a/src/video_core/shader_environment.h
+++ b/src/video_core/shader_environment.h
@@ -85,6 +85,8 @@ protected:
85 u32 cached_highest = 0; 85 u32 cached_highest = 0;
86 u32 initial_offset = 0; 86 u32 initial_offset = 0;
87 87
88 u32 viewport_transform_state = 1;
89
88 bool has_unbound_instructions = false; 90 bool has_unbound_instructions = false;
89}; 91};
90 92
@@ -102,6 +104,8 @@ public:
102 104
103 Shader::TextureType ReadTextureType(u32 handle) override; 105 Shader::TextureType ReadTextureType(u32 handle) override;
104 106
107 u32 ReadViewportTransformState() override;
108
105private: 109private:
106 Tegra::Engines::Maxwell3D* maxwell3d{}; 110 Tegra::Engines::Maxwell3D* maxwell3d{};
107 size_t stage_index{}; 111 size_t stage_index{};
@@ -120,6 +124,8 @@ public:
120 124
121 Shader::TextureType ReadTextureType(u32 handle) override; 125 Shader::TextureType ReadTextureType(u32 handle) override;
122 126
127 u32 ReadViewportTransformState() override;
128
123private: 129private:
124 Tegra::Engines::KeplerCompute* kepler_compute{}; 130 Tegra::Engines::KeplerCompute* kepler_compute{};
125}; 131};
@@ -143,6 +149,8 @@ public:
143 149
144 [[nodiscard]] Shader::TextureType ReadTextureType(u32 handle) override; 150 [[nodiscard]] Shader::TextureType ReadTextureType(u32 handle) override;
145 151
152 [[nodiscard]] u32 ReadViewportTransformState() override;
153
146 [[nodiscard]] u32 LocalMemorySize() const override; 154 [[nodiscard]] u32 LocalMemorySize() const override;
147 155
148 [[nodiscard]] u32 SharedMemorySize() const override; 156 [[nodiscard]] u32 SharedMemorySize() const override;
@@ -164,6 +172,7 @@ private:
164 u32 read_lowest{}; 172 u32 read_lowest{};
165 u32 read_highest{}; 173 u32 read_highest{};
166 u32 initial_offset{}; 174 u32 initial_offset{};
175 u32 viewport_transform_state = 1;
167}; 176};
168 177
169void SerializePipeline(std::span<const char> key, std::span<const GenericEnvironment* const> envs, 178void SerializePipeline(std::span<const char> key, std::span<const GenericEnvironment* const> envs,