Updated vulkan pipeline to support raw shaders

This commit is contained in:
Alejandro Saucedo 2020-08-31 09:24:33 +01:00
parent 8841063e31
commit 13206a9d9b
5 changed files with 119 additions and 50 deletions

View file

@ -10,6 +10,9 @@
VCPKG_WIN_PATH ?= "C:\\Users\\axsau\\Programming\\lib\\vcpkg\\scripts\\buildsystems\\vcpkg.cmake"
VCPKG_UNIX_PATH ?= "/c/Users/axsau/Programming/lib/vcpkg/scripts/buildsystems/vcpkg.cmake"
# Regext to pass to catch2 to filter tests
FILTER_TESTS ?= "*"
ifeq ($(OS),Windows_NT) # is Windows_NT on XP, 2000, 7, Vista, 10...
CMAKE_BIN ?= "C:\Program Files\CMake\bin\cmake.exe"
SCMP_BIN="C:\\VulkanSDK\\1.2.141.2\\Bin32\\glslangValidator.exe"
@ -62,7 +65,7 @@ mk_run_docs: mk_build_docs
(cd build/docs/sphinx && python2.7 -m SimpleHTTPServer)
mk_run_tests: mk_build_tests
./build/test/test_kompute
./build/test/test_kompute $(FILTER_TESTS)
####### Visual studio build shortcut commands #######
@ -91,7 +94,7 @@ vs_run_docs: vs_build_docs
(cd build/docs/sphinx && python2.7 -m SimpleHTTPServer)
vs_run_tests: vs_build_tests
./build/test/Debug/test_kompute.exe
./build/test/Debug/test_kompute.exe $(FILTER_TESTS)
####### Create release ######

View file

@ -838,12 +838,16 @@ class OpAlgoBase : public OpBase
* @param device Vulkan logical device for passing to Algorithm
* @param commandBuffer Vulkan Command Buffer to record commands into
* @param tensors Tensors that are to be used in this operation
* @param copyOutputData Whether to map device data for all output tensors back to their host data vectors
* @param shaderFilePath Optional parameter to specify the shader to load (either in spirv or raw format)
*/
OpAlgoBase(std::shared_ptr<vk::PhysicalDevice> physicalDevice,
std::shared_ptr<vk::Device> device,
std::shared_ptr<vk::CommandBuffer> commandBuffer,
std::vector<std::shared_ptr<Tensor>>& tensors,
bool copyOutputData);
bool copyOutputData = false,
std::string shaderFilePath = "",
const std::vector<char>& shaderDataRaw = {});
/**
* Default destructor, which is in charge of destroying the algorithm
@ -891,7 +895,8 @@ class OpAlgoBase : public OpBase
uint32_t mY;
uint32_t mZ;
std::string mOptSpirvBinPath; ///< Optional member variable which can be provided for the OpAlgoBase to find the data automatically and load for processing
std::string mShaderFilePath; ///< Optional member variable which can be provided for the OpAlgoBase to find the data automatically and load for processing
std::vector<char> mShaderDataRaw; ///< Optional member variable which can be provided to contain either the raw shader content or the spirv binary content
virtual std::vector<char> fetchSpirvBinaryData();
};
@ -915,12 +920,12 @@ OpAlgoBase<tX, tY, tZ>::OpAlgoBase(std::shared_ptr<vk::PhysicalDevice> physicalD
std::shared_ptr<vk::Device> device,
std::shared_ptr<vk::CommandBuffer> commandBuffer,
std::vector<std::shared_ptr<Tensor>>& tensors,
bool copyOutputData)
bool copyOutputData,
std::string shaderFilePath,
const std::vector<char>& shaderDataRaw)
: OpBase(physicalDevice, device, commandBuffer, tensors, false)
{
SPDLOG_DEBUG("Kompute OpAlgoBase constructor with params");
SPDLOG_DEBUG("Kompute OpAlgoBase configured for copy output data: {}", copyOutputData);
SPDLOG_DEBUG("Kompute OpAlgoBase constructor with params numTensors: {} copyOutputData: {}, shaderFilePath: {}", tensors.size(), copyOutputData, shaderFilePath);
// The dispatch size is set up based on either explicitly provided template
// parameters or by default it would take the shape and size of the tensors
@ -942,7 +947,9 @@ OpAlgoBase<tX, tY, tZ>::OpAlgoBase(std::shared_ptr<vk::PhysicalDevice> physicalD
this->mY,
this->mZ);
this->mShaderFilePath = shaderFilePath;
this->mCopyOutputData = copyOutputData;
this->mShaderDataRaw = shaderDataRaw;
this->mAlgorithm = std::make_shared<Algorithm>(device, commandBuffer);
}
@ -1054,24 +1061,32 @@ std::vector<char> OpAlgoBase<tX, tY, tZ>::fetchSpirvBinaryData()
SPDLOG_WARN(
"Kompute OpAlgoBase Running shaders directly from spirv file");
std::ifstream fileStream(this->mOptSpirvBinPath,
std::ios::binary | std::ios::in | std::ios::ate);
if (this->mShaderFilePath.size()) {
std::ifstream fileStream(this->mShaderFilePath,
std::ios::binary | std::ios::in | std::ios::ate);
if (!fileStream.good()) {
throw std::runtime_error("Error reading file: " + this->mOptSpirvBinPath);
if (!fileStream.good()) {
throw std::runtime_error("Error reading file: " + this->mShaderFilePath);
}
size_t shaderFileSize = fileStream.tellg();
fileStream.seekg(0, std::ios::beg);
char* shaderDataRaw = new char[shaderFileSize];
fileStream.read(shaderDataRaw, shaderFileSize);
fileStream.close();
SPDLOG_WARN(
"Kompute OpAlgoBase fetched {} bytes", shaderFileSize);
return std::vector<char>(shaderDataRaw,
shaderDataRaw + shaderFileSize);
}
else if (this->mShaderDataRaw.size()) {
return this->mShaderDataRaw;
}
else {
throw std::runtime_error("Kompute OpAlgoBase Error reached fetchSpirvBinaryData but neither filepath nor data provided");
}
size_t shaderFileSize = fileStream.tellg();
fileStream.seekg(0, std::ios::beg);
char* shaderDataRaw = new char[shaderFileSize];
fileStream.read(shaderDataRaw, shaderFileSize);
fileStream.close();
SPDLOG_WARN(
"Kompute OpAlgoBase fetched {} bytes", shaderFileSize);
return std::vector<char>(shaderDataRaw,
shaderDataRaw + shaderFileSize);
}
}
@ -1327,12 +1342,12 @@ class OpMult : public OpAlgoBase<tX, tY, tZ>
std::shared_ptr<vk::Device> device,
std::shared_ptr<vk::CommandBuffer> commandBuffer,
std::vector<std::shared_ptr<Tensor>> tensors)
: OpAlgoBase<tX, tY, tZ>(physicalDevice, device, commandBuffer, tensors, true)
: OpAlgoBase<tX, tY, tZ>(physicalDevice, device, commandBuffer, tensors, true, "")
{
SPDLOG_DEBUG("Kompute OpMult constructor with params");
#ifndef RELEASE
this->mOptSpirvBinPath = "shaders/glsl/opmult.comp";
this->mShaderFilePath = "shaders/glsl/opmult.comp";
#endif
}

View file

@ -50,12 +50,16 @@ class OpAlgoBase : public OpBase
* @param device Vulkan logical device for passing to Algorithm
* @param commandBuffer Vulkan Command Buffer to record commands into
* @param tensors Tensors that are to be used in this operation
* @param copyOutputData Whether to map device data for all output tensors back to their host data vectors
* @param shaderFilePath Optional parameter to specify the shader to load (either in spirv or raw format)
*/
OpAlgoBase(std::shared_ptr<vk::PhysicalDevice> physicalDevice,
std::shared_ptr<vk::Device> device,
std::shared_ptr<vk::CommandBuffer> commandBuffer,
std::vector<std::shared_ptr<Tensor>>& tensors,
bool copyOutputData);
bool copyOutputData = false,
std::string shaderFilePath = "",
const std::vector<char>& shaderDataRaw = {});
/**
* Default destructor, which is in charge of destroying the algorithm
@ -103,7 +107,8 @@ class OpAlgoBase : public OpBase
uint32_t mY;
uint32_t mZ;
std::string mOptSpirvBinPath; ///< Optional member variable which can be provided for the OpAlgoBase to find the data automatically and load for processing
std::string mShaderFilePath; ///< Optional member variable which can be provided for the OpAlgoBase to find the data automatically and load for processing
std::vector<char> mShaderDataRaw; ///< Optional member variable which can be provided to contain either the raw shader content or the spirv binary content
virtual std::vector<char> fetchSpirvBinaryData();
};
@ -127,12 +132,12 @@ OpAlgoBase<tX, tY, tZ>::OpAlgoBase(std::shared_ptr<vk::PhysicalDevice> physicalD
std::shared_ptr<vk::Device> device,
std::shared_ptr<vk::CommandBuffer> commandBuffer,
std::vector<std::shared_ptr<Tensor>>& tensors,
bool copyOutputData)
bool copyOutputData,
std::string shaderFilePath,
const std::vector<char>& shaderDataRaw)
: OpBase(physicalDevice, device, commandBuffer, tensors, false)
{
SPDLOG_DEBUG("Kompute OpAlgoBase constructor with params");
SPDLOG_DEBUG("Kompute OpAlgoBase configured for copy output data: {}", copyOutputData);
SPDLOG_DEBUG("Kompute OpAlgoBase constructor with params numTensors: {} copyOutputData: {}, shaderFilePath: {}", tensors.size(), copyOutputData, shaderFilePath);
// The dispatch size is set up based on either explicitly provided template
// parameters or by default it would take the shape and size of the tensors
@ -154,7 +159,9 @@ OpAlgoBase<tX, tY, tZ>::OpAlgoBase(std::shared_ptr<vk::PhysicalDevice> physicalD
this->mY,
this->mZ);
this->mShaderFilePath = shaderFilePath;
this->mCopyOutputData = copyOutputData;
this->mShaderDataRaw = shaderDataRaw;
this->mAlgorithm = std::make_shared<Algorithm>(device, commandBuffer);
}
@ -266,24 +273,32 @@ std::vector<char> OpAlgoBase<tX, tY, tZ>::fetchSpirvBinaryData()
SPDLOG_WARN(
"Kompute OpAlgoBase Running shaders directly from spirv file");
std::ifstream fileStream(this->mOptSpirvBinPath,
std::ios::binary | std::ios::in | std::ios::ate);
if (this->mShaderFilePath.size()) {
std::ifstream fileStream(this->mShaderFilePath,
std::ios::binary | std::ios::in | std::ios::ate);
if (!fileStream.good()) {
throw std::runtime_error("Error reading file: " + this->mOptSpirvBinPath);
if (!fileStream.good()) {
throw std::runtime_error("Error reading file: " + this->mShaderFilePath);
}
size_t shaderFileSize = fileStream.tellg();
fileStream.seekg(0, std::ios::beg);
char* shaderDataRaw = new char[shaderFileSize];
fileStream.read(shaderDataRaw, shaderFileSize);
fileStream.close();
SPDLOG_WARN(
"Kompute OpAlgoBase fetched {} bytes", shaderFileSize);
return std::vector<char>(shaderDataRaw,
shaderDataRaw + shaderFileSize);
}
else if (this->mShaderDataRaw.size()) {
return this->mShaderDataRaw;
}
else {
throw std::runtime_error("Kompute OpAlgoBase Error reached fetchSpirvBinaryData but neither filepath nor data provided");
}
size_t shaderFileSize = fileStream.tellg();
fileStream.seekg(0, std::ios::beg);
char* shaderDataRaw = new char[shaderFileSize];
fileStream.read(shaderDataRaw, shaderFileSize);
fileStream.close();
SPDLOG_WARN(
"Kompute OpAlgoBase fetched {} bytes", shaderFileSize);
return std::vector<char>(shaderDataRaw,
shaderDataRaw + shaderFileSize);
}
}

View file

@ -47,12 +47,12 @@ class OpMult : public OpAlgoBase<tX, tY, tZ>
std::shared_ptr<vk::Device> device,
std::shared_ptr<vk::CommandBuffer> commandBuffer,
std::vector<std::shared_ptr<Tensor>> tensors)
: OpAlgoBase<tX, tY, tZ>(physicalDevice, device, commandBuffer, tensors, true)
: OpAlgoBase<tX, tY, tZ>(physicalDevice, device, commandBuffer, tensors, true, "")
{
SPDLOG_DEBUG("Kompute OpMult constructor with params");
#ifndef RELEASE
this->mOptSpirvBinPath = "shaders/glsl/opmult.comp";
this->mShaderFilePath = "shaders/glsl/opmult.comp";
#endif
}

View file

@ -0,0 +1,36 @@
#include "catch2/catch.hpp"
#include "kompute/Kompute.hpp"
#include <fmt/ranges.h>
TEST_CASE("op_custom_simple_raw_shader") {
kp::Manager mgr;
std::shared_ptr<kp::Tensor> tensorA{ new kp::Tensor({ 3, 4, 5 })};
std::shared_ptr<kp::Tensor> tensorB{ new kp::Tensor({ 0, 0, 0 })};
mgr.evalOp<kp::OpCreateTensor>({ tensorA, tensorB });
std::string shader(
"#version 450\n"
"layout (local_size_x = 1) in;\n"
"layout(set = 0, binding = 0) buffer a { uint pa[]; };\n"
"layout(set = 0, binding = 1) buffer b { uint pb[]; };\n"
"void main() {\n"
" uint index = gl_GlobalInvocationID.x;\n"
" pb[index] = pa[index];\n"
" pa[index] = index;\n"
"}\n"
);
mgr.evalOp<kp::OpAlgoBase<>>(
{ tensorA, tensorB },
"DEFAULT",
true,
"",
std::vector<char>(shader.begin(), shader.end()));
REQUIRE(tensorA->data() == std::vector<uint32_t>{0, 1, 2});
REQUIRE(tensorB->data() == std::vector<uint32_t>{3, 4, 5});
}