VulkanShader_1.21.10-0.0.4-alpha.jar

Download file
    package net.vulkanmod.render.engine;

import com.mojang.blaze3d.buffers.GpuBuffer;
import com.mojang.blaze3d.opengl.GlConst;
import com.mojang.blaze3d.opengl.GlStateManager;
import com.mojang.blaze3d.pipeline.CompiledRenderPipeline;
import com.mojang.blaze3d.pipeline.RenderPipeline;
import com.mojang.blaze3d.shaders.ShaderType;
import com.mojang.blaze3d.systems.CommandEncoder;
import com.mojang.blaze3d.systems.GpuDevice;
import com.mojang.blaze3d.textures.GpuTexture;
import com.mojang.blaze3d.textures.GpuTextureView;
import com.mojang.blaze3d.textures.TextureFormat;
import com.mojang.logging.LogUtils;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Supplier;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.class_10141;
import net.minecraft.class_10149;
import net.minecraft.class_10867;
import net.minecraft.class_10868;
import net.minecraft.class_2960;
import net.minecraft.class_5913;
import net.minecraft.class_5944;
import net.vulkanmod.Initializer;
import net.vulkanmod.gl.VkGlTexture;
import net.vulkanmod.interfaces.shader.ExtendedRenderPipeline;
import net.vulkanmod.render.shader.ShaderLoadUtil;
import net.vulkanmod.vulkan.VRenderSystem;
import net.vulkanmod.vulkan.Vulkan;
import net.vulkanmod.vulkan.device.DeviceManager;
import net.vulkanmod.vulkan.shader.GraphicsPipeline;
import net.vulkanmod.vulkan.shader.Pipeline;
import net.vulkanmod.vulkan.shader.converter.GLSLParser;
import net.vulkanmod.vulkan.shader.converter.Lexer;
import net.vulkanmod.vulkan.shader.descriptor.UBO;
import net.vulkanmod.vulkan.texture.VulkanImage;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;

public class VkGpuDevice implements GpuDevice {
   private static final Logger LOGGER = LogUtils.getLogger();
   private final VkCommandEncoder encoder;
   private final VkDebugLabel debugLabels;
   private final int maxSupportedTextureSize;
   private final int uniformOffsetAlignment;
   private final BiFunction<class_2960, ShaderType, String> defaultShaderSource;
   private final Map<RenderPipeline, class_10867> pipelineCache = new IdentityHashMap();
   private final Map<ShaderCompilationKey, class_10141> shaderCache = new HashMap();
   private final Set<String> enabledExtensions = new HashSet();
   private final Map<ShaderCompilationKey, String> shaderSrcCache = new HashMap();

   public VkGpuDevice(long l, int i, boolean bl, BiFunction<class_2960, ShaderType, String> shaderSource, boolean bl2) {
      this.debugLabels = VkDebugLabel.create(bl2, this.enabledExtensions);
      this.maxSupportedTextureSize = VRenderSystem.maxSupportedTextureSize();
      this.uniformOffsetAlignment = (int)DeviceManager.deviceProperties.limits().minUniformBufferOffsetAlignment();
      this.defaultShaderSource = shaderSource;
      this.encoder = new VkCommandEncoder(this);
   }

   public VkDebugLabel debugLabels() {
      return this.debugLabels;
   }

   public CommandEncoder createCommandEncoder() {
      return this.encoder;
   }

   public GpuTexture createTexture(@Nullable Supplier<String> supplier, int usage, TextureFormat textureFormat, int width, int height, int layers, int mipLevels) {
      return this.createTexture(this.debugLabels.exists() && supplier != null ? (String)supplier.get() : null, usage, textureFormat, width, height, layers, mipLevels);
   }

   public GpuTexture createTexture(@Nullable String string, int usage, TextureFormat textureFormat, int width, int height, int layers, int mipLevels) {
      if (mipLevels < 1) {
         throw new IllegalArgumentException("mipLevels must be at least 1");
      } else {
         int id = VkGlTexture.genTextureId();
         if (string == null) {
            string = String.valueOf(id);
         }

         int format = VkGpuTexture.vkFormat(textureFormat);
         int viewType = VkGpuTexture.vkImageViewType(usage);
         boolean depthFormat = VulkanImage.isDepthFormat(format);
         int attachmentUsage = depthFormat ? 32 : 16;
         VulkanImage texture = VulkanImage.builder(width, height).setName(string).setFormat(format).setArrayLayers(layers).setMipLevels(mipLevels).addUsage(attachmentUsage).setViewType(viewType).createVulkanImage();
         VkGlTexture vGlTexture = VkGlTexture.getTexture(id);
         vGlTexture.setVulkanImage(texture);
         VkGlTexture.bindTexture(id);
         VkGpuTexture glTexture = new VkGpuTexture(usage, string, textureFormat, width, height, layers, mipLevels, id, vGlTexture);
         this.debugLabels.applyLabel(glTexture);
         return glTexture;
      }
   }

   public VkGpuTexture gpuTextureFromVulkanImage(VulkanImage image) {
      int id = VkGlTexture.genTextureId();
      VkGlTexture glTexture = VkGlTexture.getTexture(id);
      glTexture.setVulkanImage(image);
      TextureFormat textureFormat = VkGpuTexture.textureFormat(image.format);
      VkGpuTexture gpuTexture = new VkGpuTexture(0, image.name, textureFormat, image.width, image.height, 1, image.mipLevels, id, glTexture);
      this.debugLabels.applyLabel(gpuTexture);
      return gpuTexture;
   }

   public GpuTextureView createTextureView(GpuTexture gpuTexture) {
      return this.createTextureView(gpuTexture, 0, gpuTexture.getMipLevels());
   }

   public GpuTextureView createTextureView(GpuTexture gpuTexture, int startLevel, int levels) {
      if (gpuTexture.isClosed()) {
         throw new IllegalArgumentException("Can't create texture view with closed texture");
      } else if (startLevel >= 0 && startLevel + levels <= gpuTexture.getMipLevels()) {
         if (gpuTexture.getClass() != VkGpuTexture.class) {
            gpuTexture = VkGpuTexture.fromGlTexture((class_10868)gpuTexture);
         }

         return new VkTextureView((VkGpuTexture)gpuTexture, startLevel, levels);
      } else {
         throw new IllegalArgumentException(levels + " mip levels starting from " + startLevel + " would be out of range for texture with only " + gpuTexture.getMipLevels() + " mip levels");
      }
   }

   public GpuBuffer createBuffer(@Nullable Supplier<String> supplier, int usage, int size) {
      if (size <= 0) {
         throw new IllegalArgumentException("Buffer size must be greater than zero");
      } else {
         return new VkGpuBuffer(this.debugLabels, supplier, usage, size);
      }
   }

   public GpuBuffer createBuffer(@Nullable Supplier<String> supplier, int usage, ByteBuffer byteBuffer) {
      if (!byteBuffer.hasRemaining()) {
         throw new IllegalArgumentException("Buffer source must not be empty");
      } else {
         VkGpuBuffer glBuffer = new VkGpuBuffer(this.debugLabels, supplier, usage, byteBuffer.remaining());
         this.encoder.writeToBuffer(glBuffer.slice(), byteBuffer);
         return glBuffer;
      }
   }

   public String getImplementationInformation() {
      String var10000 = Vulkan.getDevice().vkVersion;
      return "Vulkan " + var10000 + ", " + Vulkan.getDevice().vendorIdString;
   }

   public List<String> getLastDebugMessages() {
      return Collections.emptyList();
   }

   public boolean isDebuggingEnabled() {
      return false;
   }

   public String getRenderer() {
      return "VulkanShader %s".formatted(Initializer.getVersion());
   }

   public String getVendor() {
      return Vulkan.getDevice().vendorIdString;
   }

   public String getBackendName() {
      return "Vulkan";
   }

   public String getVersion() {
      return Vulkan.getDevice().vkVersion;
   }

   private static int getMaxSupportedTextureSize() {
      int i = GlStateManager._getInteger(3379);

      for(int j = Math.max(32768, i); j >= 1024; j >>= 1) {
         GlStateManager._texImage2D(32868, 0, 6408, j, j, 0, 6408, 5121, (ByteBuffer)null);
         int k = GlStateManager._getTexLevelParameter(32868, 0, 4096);
         if (k != 0) {
            return j;
         }
      }

      int jx = Math.max(i, 1024);
      LOGGER.info("Failed to determine maximum texture size by probing, trying GL_MAX_TEXTURE_SIZE = {}", jx);
      return jx;
   }

   public int getMaxTextureSize() {
      return this.maxSupportedTextureSize;
   }

   public int getUniformOffsetAlignment() {
      return this.uniformOffsetAlignment;
   }

   public void clearPipelineCache() {
      for(class_10867 glRenderPipeline : this.pipelineCache.values()) {
         if (glRenderPipeline.comp_3802() != class_5944.field_57864) {
            glRenderPipeline.comp_3802().close();
         }
      }

      this.pipelineCache.clear();

      for(class_10141 glShaderModule : this.shaderCache.values()) {
         if (glShaderModule != class_10141.field_57880) {
            glShaderModule.close();
         }
      }

      this.shaderCache.clear();
   }

   public List<String> getEnabledExtensions() {
      return new ArrayList(this.enabledExtensions);
   }

   public void close() {
      this.clearPipelineCache();
   }

   protected class_10141 getOrCompileShader(class_2960 resourceLocation, ShaderType shaderType, class_10149 shaderDefines, BiFunction<class_2960, ShaderType, String> biFunction) {
      ShaderCompilationKey shaderCompilationKey = new ShaderCompilationKey(resourceLocation, shaderType, shaderDefines);
      return (class_10141)this.shaderCache.computeIfAbsent(shaderCompilationKey, (shaderCompilationKey2) -> this.compileShader(shaderCompilationKey, biFunction));
   }

   protected String getCachedShaderSrc(class_2960 resourceLocation, ShaderType shaderType, class_10149 shaderDefines, BiFunction<class_2960, ShaderType, String> shaderSourceGetter) {
      ShaderCompilationKey shaderCompilationKey = new ShaderCompilationKey(resourceLocation, shaderType, shaderDefines);
      return (String)this.shaderSrcCache.computeIfAbsent(shaderCompilationKey, (compilationKey) -> {
         String var10000;
         switch (shaderType) {
            case VERTEX -> var10000 = ".vsh";
            case FRAGMENT -> var10000 = ".fsh";
            default -> throw new MatchException((String)null, (Throwable)null);
         }

         String shaderExtension = var10000;
         var10000 = resourceLocation.method_12832();
         String shaderName = var10000 + shaderExtension;
         if (ShaderLoadUtil.REMAPPED_SHADERS.contains(shaderName)) {
            String src = ShaderLoadUtil.getShaderSource(resourceLocation, shaderType);
            if (src == null) {
               throw new RuntimeException("shader: (%s) not found.");
            } else {
               return src;
            }
         } else {
            return (String)shaderSourceGetter.apply(compilationKey.id, compilationKey.type);
         }
      });
   }

   public CompiledRenderPipeline precompilePipeline(RenderPipeline renderPipeline, @Nullable BiFunction<class_2960, ShaderType, String> shaderSourceGetter) {
      shaderSourceGetter = shaderSourceGetter == null ? this.defaultShaderSource : shaderSourceGetter;
      this.compilePipeline(renderPipeline, shaderSourceGetter);
      return new VkRenderPipeline(renderPipeline);
   }

   public void compilePipeline(RenderPipeline renderPipeline) {
      this.compilePipeline(renderPipeline, this.defaultShaderSource);
   }

   private class_10141 compileShader(ShaderCompilationKey shaderCompilationKey, BiFunction<class_2960, ShaderType, String> biFunction) {
      String string = (String)biFunction.apply(shaderCompilationKey.id, shaderCompilationKey.type);
      if (string == null) {
         LOGGER.error("Couldn't find source for {} shader ({})", shaderCompilationKey.type, shaderCompilationKey.id);
         return class_10141.field_57880;
      } else {
         String string2 = class_5913.method_62880(string, shaderCompilationKey.defines);
         int i = GlStateManager.glCreateShader(GlConst.toGl(shaderCompilationKey.type));
         GlStateManager.glShaderSource(i, string2);
         GlStateManager.glCompileShader(i);
         if (GlStateManager.glGetShaderi(i, 35713) == 0) {
            String string3 = StringUtils.trim(GlStateManager.glGetShaderInfoLog(i, 32768));
            LOGGER.error("Couldn't compile {} shader ({}): {}", new Object[]{shaderCompilationKey.type.getName(), shaderCompilationKey.id, string3});
            return class_10141.field_57880;
         } else {
            class_10141 glShaderModule = new class_10141(i, shaderCompilationKey.id, shaderCompilationKey.type);
            this.debugLabels.applyLabel(glShaderModule);
            return glShaderModule;
         }
      }
   }

   private void compilePipeline(RenderPipeline renderPipeline, BiFunction<class_2960, ShaderType, String> shaderSrcGetter) {
      String locationPath = renderPipeline.getLocation().method_12832();
      String configName;
      if (locationPath.contains("core")) {
         configName = locationPath.split("/")[1];
      } else {
         configName = locationPath;
      }

      Pipeline.Builder builder = new Pipeline.Builder(renderPipeline.getVertexFormat(), configName);
      ExtendedRenderPipeline extPipeline = ExtendedRenderPipeline.of(renderPipeline);
      class_2960 vertexShaderLocation = renderPipeline.getVertexShader();
      class_2960 fragmentShaderLocation = renderPipeline.getFragmentShader();
      class_10149 shaderDefines = renderPipeline.getShaderDefines();
      String vshSrc = this.getCachedShaderSrc(vertexShaderLocation, ShaderType.VERTEX, shaderDefines, shaderSrcGetter);
      String fshSrc = this.getCachedShaderSrc(fragmentShaderLocation, ShaderType.FRAGMENT, shaderDefines, shaderSrcGetter);
      vshSrc = class_5913.method_62880(vshSrc, shaderDefines);
      fshSrc = class_5913.method_62880(fshSrc, shaderDefines);
      Lexer lexer = new Lexer(vshSrc);
      GLSLParser parser = new GLSLParser();
      parser.setVertexFormat(renderPipeline.getVertexFormat());

      try {
         parser.parse(lexer, GLSLParser.Stage.VERTEX);
         lexer = new Lexer(fshSrc);
         parser.parse(lexer, GLSLParser.Stage.FRAGMENT);
      } catch (Exception e) {
         throw new RuntimeException("Caught exception while parsing: %s".formatted(renderPipeline.toString()), e);
      }

      UBO[] ubos = parser.createUBOs();
      String vshProcessed = parser.getOutput(GLSLParser.Stage.VERTEX);
      String fshProcessed = parser.getOutput(GLSLParser.Stage.FRAGMENT);
      builder.setUniforms(List.of(ubos), parser.getSamplerList());
      builder.compileShaders(configName, vshProcessed, fshProcessed);

      GraphicsPipeline pipeline;
      try {
         pipeline = builder.createGraphicsPipeline();
      } catch (Exception e) {
         e.printStackTrace();
         throw new RuntimeException("Exception while compiling pipeline %s".formatted(renderPipeline));
      }

      EGlProgram eGlProgram = new EGlProgram(1, configName);
      eGlProgram.setupUniforms(pipeline, renderPipeline.getUniforms(), renderPipeline.getSamplers());
      extPipeline.setProgram(eGlProgram);
      extPipeline.setPipeline(pipeline);
   }

   @Environment(EnvType.CLIENT)
   static record ShaderCompilationKey(class_2960 id, ShaderType type, class_10149 defines) {
      public String toString() {
         String var10000 = String.valueOf(this.id);
         String string = var10000 + " (" + String.valueOf(this.type) + ")";
         return !this.defines.method_62930() ? string + " with " + String.valueOf(this.defines) : string;
      }
   }

   private static class VkRenderPipeline implements CompiledRenderPipeline {
      final RenderPipeline renderPipeline;

      public VkRenderPipeline(RenderPipeline renderPipeline) {
         this.renderPipeline = renderPipeline;
      }

      public boolean isValid() {
         return true;
      }
   }
}
    
Download file