forked from MoonsideGames/Refresh
Compare commits
No commits in common. "d41088da896821ebf3104f19c58e9da4801eb8a3" and "f7250ab12a9710d8edf8cae7aeb3a44eb4e281b0" have entirely different histories.
d41088da89
...
f7250ab12a
|
@ -1,268 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
partial class Program
|
|
||||||
{
|
|
||||||
struct CompileShaderData
|
|
||||||
{
|
|
||||||
public string glslPath;
|
|
||||||
public string outputDir;
|
|
||||||
public bool preserveTemp;
|
|
||||||
public bool vulkan;
|
|
||||||
public bool d3d11;
|
|
||||||
public bool ps5;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void DisplayHelpText()
|
|
||||||
{
|
|
||||||
Console.WriteLine("Usage: refreshc <path-to-glsl-source | directory-with-glsl-source-files>");
|
|
||||||
Console.WriteLine("Options:");
|
|
||||||
Console.WriteLine(" --vulkan Emit shader compatible with the Refresh Vulkan backend");
|
|
||||||
Console.WriteLine(" --d3d11 Emit shader compatible with the Refresh D3D11 backend");
|
|
||||||
Console.WriteLine(" --ps5 Emit shader compatible with the Refresh PS5 backend");
|
|
||||||
Console.WriteLine(" --out dir Write output file(s) to the directory `dir`");
|
|
||||||
Console.WriteLine(" --preserve-temp Do not delete the temp directory after compilation. Useful for debugging.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int Main(string[] args)
|
|
||||||
{
|
|
||||||
if (args.Length == 0)
|
|
||||||
{
|
|
||||||
DisplayHelpText();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
CompileShaderData data = new CompileShaderData();
|
|
||||||
string inputPath = null;
|
|
||||||
|
|
||||||
for (int i = 0; i < args.Length; i += 1)
|
|
||||||
{
|
|
||||||
switch (args[i])
|
|
||||||
{
|
|
||||||
case "--vulkan":
|
|
||||||
data.vulkan = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "--d3d11":
|
|
||||||
data.d3d11 = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "--ps5":
|
|
||||||
data.ps5 = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "--out":
|
|
||||||
i += 1;
|
|
||||||
data.outputDir = args[i];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "--preserve-temp":
|
|
||||||
data.preserveTemp = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
if (inputPath == null)
|
|
||||||
{
|
|
||||||
inputPath = args[i];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.WriteLine($"refreshc: Unknown parameter {args[i]}");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!data.vulkan && !data.d3d11 && !data.ps5)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"refreshc: No Refresh platforms selected!");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !PS5
|
|
||||||
if (data.ps5)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"refreshc: `PS5` must be defined in the to target the PS5 backend!");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (data.outputDir == null)
|
|
||||||
{
|
|
||||||
data.outputDir = Directory.GetCurrentDirectory();
|
|
||||||
}
|
|
||||||
else if (!Directory.Exists(data.outputDir))
|
|
||||||
{
|
|
||||||
Console.WriteLine($"refreshc: Output directory {data.outputDir} does not exist");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Directory.Exists(inputPath))
|
|
||||||
{
|
|
||||||
// Loop over and compile each file in the directory
|
|
||||||
string[] files = Directory.GetFiles(inputPath);
|
|
||||||
foreach (string file in files)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Compiling {file}");
|
|
||||||
data.glslPath = file;
|
|
||||||
int res = CompileShader(ref data);
|
|
||||||
if (res != 0)
|
|
||||||
{
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!File.Exists(inputPath))
|
|
||||||
{
|
|
||||||
Console.WriteLine($"refreshc: glsl source file or directory ({inputPath}) does not exist");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
data.glslPath = inputPath;
|
|
||||||
int res = CompileShader(ref data);
|
|
||||||
if (res != 0)
|
|
||||||
{
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int CompileShader(ref CompileShaderData data)
|
|
||||||
{
|
|
||||||
int res = 0;
|
|
||||||
string shaderName = Path.GetFileNameWithoutExtension(data.glslPath);
|
|
||||||
string shaderType = Path.GetExtension(data.glslPath);
|
|
||||||
|
|
||||||
if (shaderType != ".vert" && shaderType != ".frag" && shaderType != ".comp")
|
|
||||||
{
|
|
||||||
Console.WriteLine("refreshc: Expected glsl source file with extension '.vert', '.frag', or '.comp'");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the temp directory, if needed
|
|
||||||
string tempDir = Path.Combine(Directory.GetCurrentDirectory(), "temp");
|
|
||||||
if (!Directory.Exists(tempDir))
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(tempDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compile to spirv
|
|
||||||
string spirvPath = Path.Combine(tempDir, $"{shaderName}.spv");
|
|
||||||
res = CompileGlslToSpirv(data.glslPath, shaderName, spirvPath);
|
|
||||||
if (res != 0)
|
|
||||||
{
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.d3d11 || data.ps5)
|
|
||||||
{
|
|
||||||
// Transpile to hlsl
|
|
||||||
string hlslPath = Path.Combine(tempDir, $"{shaderName}.hlsl");
|
|
||||||
res = TranslateSpirvToHlsl(spirvPath, hlslPath);
|
|
||||||
if (res != 0)
|
|
||||||
{
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: Is there a cross-platform way to compile HLSL to DXBC?
|
|
||||||
|
|
||||||
#if PS5
|
|
||||||
// Transpile to ps5, if requested
|
|
||||||
if (data.ps5)
|
|
||||||
{
|
|
||||||
res = TranslateHlslToPS5(hlslPath, shaderName, shaderType, tempDir);
|
|
||||||
if (res != 0)
|
|
||||||
{
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the output blob file
|
|
||||||
string outputFilepath = Path.Combine(data.outputDir, $"{shaderName}.refresh");
|
|
||||||
using (FileStream fs = File.Create(outputFilepath))
|
|
||||||
{
|
|
||||||
using (BinaryWriter writer = new BinaryWriter(fs))
|
|
||||||
{
|
|
||||||
// Magic
|
|
||||||
writer.Write(new char[] { 'R', 'F', 'S', 'H'});
|
|
||||||
|
|
||||||
if (data.vulkan)
|
|
||||||
{
|
|
||||||
string inputPath = Path.Combine(tempDir, $"{shaderName}.spv");
|
|
||||||
WriteShaderBlob(writer, inputPath, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if PS5
|
|
||||||
if (data.ps5)
|
|
||||||
{
|
|
||||||
string ext = GetPS5ShaderFileExtension();
|
|
||||||
string inputPath = Path.Combine(tempDir, $"{shaderName}{ext}");
|
|
||||||
WriteShaderBlob(writer, inputPath, 2);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (data.d3d11)
|
|
||||||
{
|
|
||||||
string inputPath = Path.Combine(tempDir, $"{shaderName}.hlsl");
|
|
||||||
WriteShaderBlob(writer, inputPath, 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
// Clean up the temp directory
|
|
||||||
if (!data.preserveTemp)
|
|
||||||
{
|
|
||||||
Directory.Delete(tempDir, true);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void WriteShaderBlob(BinaryWriter writer, string inputPath, byte backend)
|
|
||||||
{
|
|
||||||
byte[] shaderBlob = File.ReadAllBytes(inputPath);
|
|
||||||
writer.Write(backend); // Corresponds to Refresh_Backend
|
|
||||||
writer.Write(shaderBlob.Length);
|
|
||||||
writer.Write(shaderBlob);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int CompileGlslToSpirv(string glslPath, string shaderName, string outputPath)
|
|
||||||
{
|
|
||||||
Process glslc = Process.Start(
|
|
||||||
"glslc",
|
|
||||||
$"{glslPath} -o {outputPath}"
|
|
||||||
);
|
|
||||||
glslc.WaitForExit();
|
|
||||||
if (glslc.ExitCode != 0)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"refreshc: Could not compile GLSL code");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int TranslateSpirvToHlsl(string spirvPath, string outputPath)
|
|
||||||
{
|
|
||||||
Process spirvcross = Process.Start(
|
|
||||||
"spirv-cross",
|
|
||||||
$"{spirvPath} --hlsl --shader-model 50 --output {outputPath}"
|
|
||||||
);
|
|
||||||
spirvcross.WaitForExit();
|
|
||||||
if (spirvcross.ExitCode != 0)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"refreshc: Could not translate SPIR-V to HLSL");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<OutputType>Exe</OutputType>
|
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
|
||||||
<TargetName>refreshc</TargetName>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
|
@ -338,52 +338,10 @@ Refresh_ShaderModule* Refresh_CreateShaderModule(
|
||||||
Refresh_Device *device,
|
Refresh_Device *device,
|
||||||
Refresh_ShaderModuleCreateInfo *shaderModuleCreateInfo
|
Refresh_ShaderModuleCreateInfo *shaderModuleCreateInfo
|
||||||
) {
|
) {
|
||||||
Refresh_ShaderModuleCreateInfo driverSpecificCreateInfo = { 0, NULL };
|
|
||||||
uint8_t *bytes;
|
|
||||||
uint32_t i, size;
|
|
||||||
|
|
||||||
NULL_RETURN_NULL(device);
|
NULL_RETURN_NULL(device);
|
||||||
|
|
||||||
/* verify the magic number in the shader blob header */
|
|
||||||
bytes = (uint8_t*) shaderModuleCreateInfo->byteCode;
|
|
||||||
if (bytes[0] != 'R' || bytes[1] != 'F' || bytes[2] != 'S' || bytes[3] != 'H')
|
|
||||||
{
|
|
||||||
Refresh_LogError("Cannot parse malformed Refresh shader blob!");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* find the code for the selected backend */
|
|
||||||
i = 4;
|
|
||||||
while (i < shaderModuleCreateInfo->codeSize)
|
|
||||||
{
|
|
||||||
size = *((uint32_t*) &bytes[i + 1]);
|
|
||||||
|
|
||||||
if (bytes[i] == (uint8_t) selectedBackend)
|
|
||||||
{
|
|
||||||
driverSpecificCreateInfo.codeSize = size;
|
|
||||||
driverSpecificCreateInfo.byteCode = (uint32_t*) &bytes[i + 1 + sizeof(uint32_t)];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* skip over the backend byte, the blob size, and the blob */
|
|
||||||
i += 1 + sizeof(uint32_t) + size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* verify the shader blob supports the selected backend */
|
|
||||||
if (driverSpecificCreateInfo.byteCode == NULL)
|
|
||||||
{
|
|
||||||
Refresh_LogError(
|
|
||||||
"Cannot create shader module that does not contain shader code for the selected backend! "
|
|
||||||
"Recompile your shader and enable this backend."
|
|
||||||
);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return device->CreateShaderModule(
|
return device->CreateShaderModule(
|
||||||
device->driverData,
|
device->driverData,
|
||||||
&driverSpecificCreateInfo
|
shaderModuleCreateInfo
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5221,6 +5221,7 @@ static VulkanTexture* VULKAN_INTERNAL_CreateTexture(
|
||||||
uint32_t levelCount,
|
uint32_t levelCount,
|
||||||
VkFormat format,
|
VkFormat format,
|
||||||
VkImageAspectFlags aspectMask,
|
VkImageAspectFlags aspectMask,
|
||||||
|
VkImageType imageType,
|
||||||
VkImageUsageFlags imageUsageFlags
|
VkImageUsageFlags imageUsageFlags
|
||||||
) {
|
) {
|
||||||
VkResult vulkanResult;
|
VkResult vulkanResult;
|
||||||
|
@ -5254,7 +5255,7 @@ static VulkanTexture* VULKAN_INTERNAL_CreateTexture(
|
||||||
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||||
imageCreateInfo.pNext = NULL;
|
imageCreateInfo.pNext = NULL;
|
||||||
imageCreateInfo.flags = imageCreateFlags;
|
imageCreateInfo.flags = imageCreateFlags;
|
||||||
imageCreateInfo.imageType = is3D ? VK_IMAGE_TYPE_3D : VK_IMAGE_TYPE_2D;
|
imageCreateInfo.imageType = imageType;
|
||||||
imageCreateInfo.format = format;
|
imageCreateInfo.format = format;
|
||||||
imageCreateInfo.extent.width = width;
|
imageCreateInfo.extent.width = width;
|
||||||
imageCreateInfo.extent.height = height;
|
imageCreateInfo.extent.height = height;
|
||||||
|
@ -5359,13 +5360,17 @@ static VulkanTexture* VULKAN_INTERNAL_CreateTexture(
|
||||||
{
|
{
|
||||||
imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_CUBE;
|
imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_CUBE;
|
||||||
}
|
}
|
||||||
else if (is3D)
|
else if (imageType == VK_IMAGE_TYPE_2D)
|
||||||
|
{
|
||||||
|
imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||||
|
}
|
||||||
|
else if (imageType == VK_IMAGE_TYPE_3D)
|
||||||
{
|
{
|
||||||
imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_3D;
|
imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_3D;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
Refresh_LogError("invalid image type: %u", imageType);
|
||||||
}
|
}
|
||||||
|
|
||||||
vulkanResult = renderer->vkCreateImageView(
|
vulkanResult = renderer->vkCreateImageView(
|
||||||
|
@ -5449,6 +5454,7 @@ static VulkanRenderTarget* VULKAN_INTERNAL_CreateRenderTarget(
|
||||||
1,
|
1,
|
||||||
vulkanTexture->format,
|
vulkanTexture->format,
|
||||||
aspectFlags,
|
aspectFlags,
|
||||||
|
VK_IMAGE_TYPE_2D,
|
||||||
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT
|
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -6655,6 +6661,7 @@ static Refresh_Texture* VULKAN_CreateTexture(
|
||||||
textureCreateInfo->levelCount,
|
textureCreateInfo->levelCount,
|
||||||
format,
|
format,
|
||||||
imageAspectFlags,
|
imageAspectFlags,
|
||||||
|
VK_IMAGE_TYPE_2D,
|
||||||
imageUsageFlags
|
imageUsageFlags
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue