Implementing basic asset serialization
This commit is contained in:
@@ -12,8 +12,6 @@ target_sources(Engine
|
||||
Mesh.cpp
|
||||
MeshBatch.h
|
||||
MeshBatch.cpp
|
||||
RenderMaterial.h
|
||||
RenderMaterial.cpp
|
||||
ShaderCompiler.h
|
||||
ShaderCompiler.cpp
|
||||
VertexShaderInput.h
|
||||
@@ -31,7 +29,6 @@ target_sources(Engine
|
||||
Graphics.h
|
||||
Mesh.h
|
||||
MeshBatch.h
|
||||
RenderMaterial.h
|
||||
ShaderCompiler.h
|
||||
VertexShaderInput.h
|
||||
StaticMeshVertexInput.h)
|
||||
|
||||
@@ -1,6 +1,117 @@
|
||||
#include "GraphicsEnums.h"
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Gfx;
|
||||
|
||||
uint32 Gfx::currentFrameIndex = 0;
|
||||
double Gfx::currentFrameDelta = 0;
|
||||
double Gfx::currentFrameDelta = 0;
|
||||
|
||||
FormatCompatibilityInfo Gfx::getFormatInfo(SeFormat format)
|
||||
{
|
||||
switch(format) {
|
||||
case SE_FORMAT_R4G4_UNORM_PACK8:
|
||||
case SE_FORMAT_R8_UNORM:
|
||||
case SE_FORMAT_R8_SNORM:
|
||||
case SE_FORMAT_R8_USCALED:
|
||||
case SE_FORMAT_R8_SSCALED:
|
||||
case SE_FORMAT_R8_UINT:
|
||||
case SE_FORMAT_R8_SINT:
|
||||
case SE_FORMAT_R8_SRGB:
|
||||
return FormatCompatibilityInfo {
|
||||
.blockSize = 1,
|
||||
.blockExtent = UVector(1, 1, 1),
|
||||
.texelsPerBlock = 1,
|
||||
};
|
||||
case SE_FORMAT_R10X6_UNORM_PACK16:
|
||||
case SE_FORMAT_R12X4_UNORM_PACK16:
|
||||
//case SE_FORMAT_A4R4G4B4_UNORM_PACK16:
|
||||
//case SE_FORMAT_A4B4G4R4_UNORM_PACK16:
|
||||
case SE_FORMAT_R4G4B4A4_UNORM_PACK16:
|
||||
case SE_FORMAT_B4G4R4A4_UNORM_PACK16:
|
||||
case SE_FORMAT_R5G6B5_UNORM_PACK16:
|
||||
case SE_FORMAT_B5G6R5_UNORM_PACK16:
|
||||
case SE_FORMAT_R5G5B5A1_UNORM_PACK16:
|
||||
case SE_FORMAT_B5G5R5A1_UNORM_PACK16:
|
||||
case SE_FORMAT_A1R5G5B5_UNORM_PACK16:
|
||||
case SE_FORMAT_R8G8_UNORM:
|
||||
case SE_FORMAT_R8G8_SNORM:
|
||||
case SE_FORMAT_R8G8_USCALED:
|
||||
case SE_FORMAT_R8G8_SSCALED:
|
||||
case SE_FORMAT_R8G8_UINT:
|
||||
case SE_FORMAT_R8G8_SINT:
|
||||
case SE_FORMAT_R8G8_SRGB:
|
||||
case SE_FORMAT_R16_UNORM:
|
||||
case SE_FORMAT_R16_SNORM:
|
||||
case SE_FORMAT_R16_USCALED:
|
||||
case SE_FORMAT_R16_SSCALED:
|
||||
case SE_FORMAT_R16_UINT:
|
||||
case SE_FORMAT_R16_SINT:
|
||||
case SE_FORMAT_R16_SFLOAT:
|
||||
return FormatCompatibilityInfo {
|
||||
.blockSize = 2,
|
||||
.blockExtent = UVector(1, 1, 1),
|
||||
.texelsPerBlock = 1,
|
||||
};
|
||||
case SE_FORMAT_BC7_UNORM_BLOCK:
|
||||
case SE_FORMAT_BC7_SRGB_BLOCK:
|
||||
return FormatCompatibilityInfo {
|
||||
.blockSize = 16,
|
||||
.blockExtent = UVector(4, 4, 1),
|
||||
.texelsPerBlock = 16,
|
||||
};
|
||||
case SE_FORMAT_R10X6G10X6_UNORM_2PACK16:
|
||||
case SE_FORMAT_R12X4G12X4_UNORM_2PACK16:
|
||||
//case SE_FORMAT_R16G16_S10_5_NV:
|
||||
case SE_FORMAT_R8G8B8A8_UNORM:
|
||||
case SE_FORMAT_R8G8B8A8_SNORM:
|
||||
case SE_FORMAT_R8G8B8A8_USCALED:
|
||||
case SE_FORMAT_R8G8B8A8_SSCALED:
|
||||
case SE_FORMAT_R8G8B8A8_UINT:
|
||||
case SE_FORMAT_R8G8B8A8_SINT:
|
||||
case SE_FORMAT_R8G8B8A8_SRGB:
|
||||
case SE_FORMAT_B8G8R8A8_UNORM:
|
||||
case SE_FORMAT_B8G8R8A8_SNORM:
|
||||
case SE_FORMAT_B8G8R8A8_USCALED:
|
||||
case SE_FORMAT_B8G8R8A8_SSCALED:
|
||||
case SE_FORMAT_B8G8R8A8_UINT:
|
||||
case SE_FORMAT_B8G8R8A8_SINT:
|
||||
case SE_FORMAT_B8G8R8A8_SRGB:
|
||||
case SE_FORMAT_A8B8G8R8_UNORM_PACK32:
|
||||
case SE_FORMAT_A8B8G8R8_SNORM_PACK32:
|
||||
case SE_FORMAT_A8B8G8R8_USCALED_PACK32:
|
||||
case SE_FORMAT_A8B8G8R8_SSCALED_PACK32:
|
||||
case SE_FORMAT_A8B8G8R8_UINT_PACK32:
|
||||
case SE_FORMAT_A8B8G8R8_SINT_PACK32:
|
||||
case SE_FORMAT_A8B8G8R8_SRGB_PACK32:
|
||||
case SE_FORMAT_A2R10G10B10_UNORM_PACK32:
|
||||
case SE_FORMAT_A2R10G10B10_SNORM_PACK32:
|
||||
case SE_FORMAT_A2R10G10B10_USCALED_PACK32:
|
||||
case SE_FORMAT_A2R10G10B10_SSCALED_PACK32:
|
||||
case SE_FORMAT_A2R10G10B10_UINT_PACK32:
|
||||
case SE_FORMAT_A2R10G10B10_SINT_PACK32:
|
||||
case SE_FORMAT_A2B10G10R10_UNORM_PACK32:
|
||||
case SE_FORMAT_A2B10G10R10_SNORM_PACK32:
|
||||
case SE_FORMAT_A2B10G10R10_USCALED_PACK32:
|
||||
case SE_FORMAT_A2B10G10R10_SSCALED_PACK32:
|
||||
case SE_FORMAT_A2B10G10R10_UINT_PACK32:
|
||||
case SE_FORMAT_A2B10G10R10_SINT_PACK32:
|
||||
case SE_FORMAT_R16G16_UNORM:
|
||||
case SE_FORMAT_R16G16_SNORM:
|
||||
case SE_FORMAT_R16G16_USCALED:
|
||||
case SE_FORMAT_R16G16_SSCALED:
|
||||
case SE_FORMAT_R16G16_UINT:
|
||||
case SE_FORMAT_R16G16_SINT:
|
||||
case SE_FORMAT_R16G16_SFLOAT:
|
||||
case SE_FORMAT_R32_UINT:
|
||||
case SE_FORMAT_R32_SINT:
|
||||
case SE_FORMAT_R32_SFLOAT:
|
||||
case SE_FORMAT_B10G11R11_UFLOAT_PACK32:
|
||||
case SE_FORMAT_E5B9G9R9_UFLOAT_PACK32:
|
||||
return FormatCompatibilityInfo{
|
||||
.blockSize = 4,
|
||||
.blockExtent = Vector(1, 1, 1),
|
||||
.texelsPerBlock = 1,
|
||||
};
|
||||
}
|
||||
throw new std::logic_error("not yet implemented");
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "MinimalEngine.h"
|
||||
#include "Math/Vector.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
@@ -1003,6 +1004,16 @@ typedef enum SeFormat
|
||||
SE_FORMAT_MAX_ENUM = 0x7FFFFFFF
|
||||
} SeFormat;
|
||||
|
||||
struct FormatCompatibilityInfo
|
||||
{
|
||||
// std::string class
|
||||
uint32 blockSize;
|
||||
UVector blockExtent;
|
||||
uint32 texelsPerBlock;
|
||||
};
|
||||
|
||||
FormatCompatibilityInfo getFormatInfo(SeFormat format);
|
||||
|
||||
typedef enum SeImageType
|
||||
{
|
||||
SE_IMAGE_TYPE_1D = 0,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#pragma once
|
||||
#include "GraphicsEnums.h"
|
||||
#include "Containers/Map.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
|
||||
struct GraphicsInitializer
|
||||
{
|
||||
const char *applicationName;
|
||||
|
||||
@@ -94,7 +94,7 @@ ShaderCollection& ShaderMap::createShaders(
|
||||
|
||||
return collection;
|
||||
}
|
||||
void DescriptorLayout::addDescriptorBinding(uint32 bindingIndex, SeDescriptorType type, uint32 arrayCount, SeDescriptorBindingFlags bindingFlags)
|
||||
void DescriptorLayout::addDescriptorBinding(uint32 bindingIndex, SeDescriptorType type, uint32 arrayCount, SeDescriptorBindingFlags bindingFlags, SeShaderStageFlags shaderStages)
|
||||
{
|
||||
if (descriptorBindings.size() <= bindingIndex)
|
||||
{
|
||||
@@ -105,6 +105,7 @@ void DescriptorLayout::addDescriptorBinding(uint32 bindingIndex, SeDescriptorTyp
|
||||
binding.descriptorType = type;
|
||||
binding.descriptorCount = arrayCount;
|
||||
binding.bindingFlags = bindingFlags;
|
||||
binding.shaderStages = shaderStages;
|
||||
}
|
||||
|
||||
PDescriptorSet DescriptorLayout::allocateDescriptorSet()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include "Math/Math.h"
|
||||
#include "GraphicsEnums.h"
|
||||
#include "Containers/Array.h"
|
||||
#include "Containers/List.h"
|
||||
@@ -158,9 +159,9 @@ public:
|
||||
: binding(other.binding), descriptorType(other.descriptorType), descriptorCount(other.descriptorCount), shaderStages(other.shaderStages)
|
||||
{
|
||||
}
|
||||
uint32_t binding;
|
||||
uint32 binding;
|
||||
SeDescriptorType descriptorType;
|
||||
uint32_t descriptorCount;
|
||||
uint32 descriptorCount;
|
||||
SeDescriptorBindingFlags bindingFlags = 0;
|
||||
SeShaderStageFlags shaderStages;
|
||||
};
|
||||
@@ -217,11 +218,12 @@ public:
|
||||
return *this;
|
||||
}
|
||||
virtual void create() = 0;
|
||||
virtual void addDescriptorBinding(uint32 binding, SeDescriptorType type, uint32 arrayCount = 1, SeDescriptorBindingFlags bindingFlags = 0);
|
||||
virtual void addDescriptorBinding(uint32 binding, SeDescriptorType type, uint32 arrayCount = 1, SeDescriptorBindingFlags bindingFlags = 0, SeShaderStageFlags shaderStages = SeShaderStageFlagBits::SE_SHADER_STAGE_ALL);
|
||||
virtual void reset();
|
||||
virtual PDescriptorSet allocateDescriptorSet();
|
||||
const Array<DescriptorBinding> &getBindings() const { return descriptorBindings; }
|
||||
inline uint32 getSetIndex() const { return setIndex; }
|
||||
constexpr uint32 getSetIndex() const { return setIndex; }
|
||||
constexpr void setSetIndex(uint32 _setIndex) { setIndex = _setIndex; }
|
||||
|
||||
protected:
|
||||
Array<DescriptorBinding> descriptorBindings;
|
||||
@@ -371,7 +373,7 @@ public:
|
||||
}
|
||||
|
||||
virtual void updateRegion(BulkResourceData update) = 0;
|
||||
|
||||
virtual void download(Array<uint8>& buffer) = 0;
|
||||
protected:
|
||||
// Inherited via QueueOwnedResource
|
||||
virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
|
||||
@@ -396,6 +398,7 @@ public:
|
||||
return indexType;
|
||||
}
|
||||
|
||||
virtual void download(Array<uint8>& buffer) = 0;
|
||||
protected:
|
||||
// Inherited via QueueOwnedResource
|
||||
virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
|
||||
@@ -543,6 +546,7 @@ public:
|
||||
virtual uint32 getSizeX() const = 0;
|
||||
virtual uint32 getSizeY() const = 0;
|
||||
virtual uint32 getSizeZ() const = 0;
|
||||
virtual uint32 getNumFaces() const { return 1; }
|
||||
virtual SeSampleCountFlags getNumSamples() const = 0;
|
||||
virtual uint32 getMipLevels() const = 0;
|
||||
virtual void changeLayout(SeImageLayout newLayout) = 0;
|
||||
@@ -550,6 +554,7 @@ public:
|
||||
virtual class Texture3D* getTexture3D() { return nullptr; }
|
||||
virtual class TextureCube* getTextureCube() { return nullptr; }
|
||||
virtual void* getNativeHandle() { return nullptr; }
|
||||
virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer) = 0;
|
||||
protected:
|
||||
// Inherited via QueueOwnedResource
|
||||
virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
|
||||
@@ -612,6 +617,7 @@ public:
|
||||
virtual uint32 getSizeX() const = 0;
|
||||
virtual uint32 getSizeY() const = 0;
|
||||
virtual uint32 getSizeZ() const = 0;
|
||||
virtual uint32 getNumFaces() const { return 6; }
|
||||
virtual SeSampleCountFlags getNumSamples() const = 0;
|
||||
virtual uint32 getMipLevels() const = 0;
|
||||
virtual void changeLayout(SeImageLayout newLayout) = 0;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "Mesh.h"
|
||||
#include "VertexShaderInput.h"
|
||||
#include "Graphics/Graphics.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include "GraphicsResources.h"
|
||||
#include "Material/MaterialInterface.h"
|
||||
#include "Asset/MaterialAsset.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
@@ -14,7 +14,7 @@ public:
|
||||
|
||||
Gfx::PIndexBuffer indexBuffer;
|
||||
PVertexShaderInput vertexInput;
|
||||
PMaterialInterface referencedMaterial;
|
||||
PMaterialAsset referencedMaterial;
|
||||
private:
|
||||
};
|
||||
DEFINE_REF(Mesh)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "GraphicsResources.h"
|
||||
#include "VertexShaderInput.h"
|
||||
#include "Material/MaterialInterface.h"
|
||||
#include "Graphics/Graphics.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "GraphicsEnums.h"
|
||||
#include "Containers/Array.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
@@ -47,8 +48,4 @@ struct MeshBatch
|
||||
MeshBatch& operator=(const MeshBatch& other) = default;
|
||||
MeshBatch& operator=(MeshBatch&& other) = default;
|
||||
};
|
||||
struct StaticMeshBatch : public MeshBatch
|
||||
{
|
||||
uint32 index;
|
||||
};
|
||||
} // namespace Seele
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
#include "RenderMaterial.h"
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Gfx;
|
||||
@@ -1,44 +0,0 @@
|
||||
#pragma once
|
||||
#include "GraphicsResources.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
namespace Gfx
|
||||
{
|
||||
class MaterialShaderMap;//TODO implement
|
||||
class MaterialRenderContext;
|
||||
struct UniformExpressionCache
|
||||
{
|
||||
Gfx::PUniformBuffer uniformBuffer;
|
||||
uint8 bUpToDate;
|
||||
|
||||
const MaterialShaderMap* cachedUniformExpressionShaderMap;
|
||||
};
|
||||
class Material;
|
||||
class RenderMaterial
|
||||
{
|
||||
public:
|
||||
mutable UniformExpressionCache uniformExpressionCache;
|
||||
RenderMaterial();
|
||||
virtual ~RenderMaterial();
|
||||
|
||||
void evaluateUniformExpressions(UniformExpressionCache& outUniforExpressionCache, const MaterialRenderContext& context);
|
||||
|
||||
void cacheUniformExpressions(bool bRecreatueUniformBuffer);
|
||||
|
||||
void invalidateUniformExpressionCache(bool bRecreateUniformBuffer);
|
||||
|
||||
void updateUniformExpressionCacheIfNeeded() const;
|
||||
|
||||
const Material* getMaterial() const
|
||||
{
|
||||
const RenderMaterial* unused = nullptr;
|
||||
return &getMaterialWithFallback(unused);
|
||||
}
|
||||
|
||||
virtual const Material& getMaterialWithFallback(const RenderMaterial*& outFallbackRenderMaterial) const = 0;
|
||||
|
||||
virtual Material* getMaterialNoFallback() const { return nullptr; }
|
||||
};
|
||||
} // namespace Gfx
|
||||
} // namespace Seele
|
||||
@@ -35,6 +35,11 @@ void BasePassMeshProcessor::processMeshBatch(
|
||||
const PVertexShaderInput vertexInput = batch.vertexInput;
|
||||
|
||||
const Gfx::ShaderCollection* collection = material->getShaders(Gfx::RenderPassType::BasePass, vertexInput->getType());
|
||||
if(collection == nullptr)
|
||||
{
|
||||
material->createShaders(graphics, Gfx::RenderPassType::BasePass, vertexInput->getType());
|
||||
collection = material->getShaders(Gfx::RenderPassType::BasePass, vertexInput->getType());
|
||||
}
|
||||
assert(collection != nullptr);
|
||||
|
||||
Gfx::PRenderCommand renderCommand = graphics->createRenderCommand();
|
||||
@@ -158,7 +163,7 @@ void BasePass::render()
|
||||
descriptorSets[INDEX_LIGHT_ENV]->writeChanges();
|
||||
|
||||
graphics->beginRenderPass(renderPass);
|
||||
for (auto &&meshBatch : passData.staticDrawList)
|
||||
for (const auto& meshBatch : passData.staticDrawList)
|
||||
{
|
||||
processor->processMeshBatch(meshBatch, viewport, renderPass, basePassLayout, primitiveLayout, descriptorSets);
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ DEFINE_REF(BasePassMeshProcessor)
|
||||
DECLARE_REF(CameraActor)
|
||||
struct BasePassData
|
||||
{
|
||||
Array<StaticMeshBatch> staticDrawList;
|
||||
Array<MeshBatch> staticDrawList;
|
||||
Gfx::PStructuredBuffer sceneDataBuffer;
|
||||
};
|
||||
class BasePass : public RenderPass<BasePassData>
|
||||
|
||||
@@ -34,6 +34,11 @@ void DepthPrepassMeshProcessor::processMeshBatch(
|
||||
const PVertexShaderInput vertexInput = batch.vertexInput;
|
||||
|
||||
const Gfx::ShaderCollection* collection = material->getShaders(Gfx::RenderPassType::DepthPrepass, vertexInput->getType());
|
||||
if (collection == nullptr)
|
||||
{
|
||||
material->createShaders(graphics, Gfx::RenderPassType::DepthPrepass, vertexInput->getType());
|
||||
collection = material->getShaders(Gfx::RenderPassType::DepthPrepass, vertexInput->getType());
|
||||
}
|
||||
assert(collection != nullptr);
|
||||
|
||||
Gfx::PRenderCommand renderCommand = graphics->createRenderCommand();
|
||||
@@ -128,7 +133,7 @@ void DepthPrepass::render()
|
||||
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
|
||||
depthAttachment->getTexture()->transferOwnership(Gfx::QueueType::GRAPHICS);
|
||||
graphics->beginRenderPass(renderPass);
|
||||
for (auto &&meshBatch : passData.staticDrawList)
|
||||
for (const auto& meshBatch : passData.staticDrawList)
|
||||
{
|
||||
processor->processMeshBatch(meshBatch, viewport, renderPass, depthPrepassLayout, primitiveLayout, descriptorSets);
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ private:
|
||||
DEFINE_REF(DepthPrepassMeshProcessor)
|
||||
struct DepthPrepassData
|
||||
{
|
||||
Array<StaticMeshBatch> staticDrawList;
|
||||
Array<MeshBatch> staticDrawList;
|
||||
Gfx::PStructuredBuffer sceneDataBuffer;
|
||||
};
|
||||
class DepthPrepass : public RenderPass<DepthPrepassData>
|
||||
|
||||
@@ -47,16 +47,15 @@ void StaticMeshVertexInput::init(Gfx::PGraphics graphics)
|
||||
{
|
||||
elements.add(accessStreamComponent(VertexStreamComponent(graphics->getNullVertexBuffer(), 0, 0, Gfx::SE_FORMAT_R32G32B32A32_SFLOAT), 4));
|
||||
}
|
||||
if(data.textureCoordinates.size())
|
||||
const int32 baseTexCoordAttribute = 5;
|
||||
for(uint32 coordinateIndex = 0; coordinateIndex < MAX_TEXCOORDS; ++coordinateIndex)
|
||||
{
|
||||
const int32 baseTexCoordAttribute = 5;
|
||||
for(uint32 coordinateIndex = 0; coordinateIndex < data.textureCoordinates.size(); ++coordinateIndex)
|
||||
{
|
||||
elements.add(accessStreamComponent(
|
||||
data.textureCoordinates[coordinateIndex],
|
||||
static_cast<uint8>(baseTexCoordAttribute + coordinateIndex)
|
||||
));
|
||||
}
|
||||
if (data.textureCoordinates[coordinateIndex].vertexBuffer == nullptr)
|
||||
continue;
|
||||
elements.add(accessStreamComponent(
|
||||
data.textureCoordinates[coordinateIndex],
|
||||
static_cast<uint8>(baseTexCoordAttribute + coordinateIndex)
|
||||
));
|
||||
}
|
||||
initDeclaration(graphics, elements);
|
||||
}
|
||||
@@ -66,4 +65,17 @@ void StaticMeshVertexInput::setData(StaticMeshDataType&& _data)
|
||||
data = std::move(_data);
|
||||
}
|
||||
|
||||
void StaticMeshVertexInput::save(ArchiveBuffer& buffer)
|
||||
{
|
||||
Serialization::save(buffer, name);
|
||||
Serialization::save(buffer, data);
|
||||
}
|
||||
|
||||
void StaticMeshVertexInput::load(ArchiveBuffer& buffer)
|
||||
{
|
||||
Serialization::load(buffer, name);
|
||||
Serialization::load(buffer, data);
|
||||
init(buffer.getGraphics());
|
||||
}
|
||||
|
||||
IMPLEMENT_VERTEX_INPUT_TYPE(StaticMeshVertexInput, "StaticMeshVertexInput")
|
||||
@@ -10,7 +10,7 @@ struct StaticMeshDataType
|
||||
VertexStreamComponent tangentBasisComponents[3];
|
||||
|
||||
//Dont forget these are 4 component vectors
|
||||
Array<VertexStreamComponent> textureCoordinates;
|
||||
VertexStreamComponent textureCoordinates[4];
|
||||
|
||||
VertexStreamComponent colorComponent;
|
||||
};
|
||||
@@ -21,9 +21,38 @@ public:
|
||||
StaticMeshVertexInput(std::string name);
|
||||
virtual ~StaticMeshVertexInput();
|
||||
virtual void init(Gfx::PGraphics graphics) override;
|
||||
virtual void save(ArchiveBuffer& buffer) override;
|
||||
virtual void load(ArchiveBuffer& buffer) override;
|
||||
void setData(StaticMeshDataType&& data);
|
||||
private:
|
||||
StaticMeshDataType data;
|
||||
};
|
||||
DEFINE_REF(StaticMeshVertexInput)
|
||||
}
|
||||
namespace Serialization
|
||||
{
|
||||
static void save(ArchiveBuffer& buffer, StaticMeshDataType& type)
|
||||
{
|
||||
Serialization::save(buffer, type.positionStream);
|
||||
Serialization::save(buffer, type.tangentBasisComponents[0]);
|
||||
Serialization::save(buffer, type.tangentBasisComponents[1]);
|
||||
Serialization::save(buffer, type.tangentBasisComponents[2]);
|
||||
Serialization::save(buffer, type.textureCoordinates[0]);
|
||||
Serialization::save(buffer, type.textureCoordinates[1]);
|
||||
Serialization::save(buffer, type.textureCoordinates[2]);
|
||||
Serialization::save(buffer, type.textureCoordinates[3]);
|
||||
Serialization::save(buffer, type.colorComponent);
|
||||
}
|
||||
static void load(ArchiveBuffer& buffer, StaticMeshDataType& type)
|
||||
{
|
||||
Serialization::load(buffer, type.positionStream);
|
||||
Serialization::load(buffer, type.tangentBasisComponents[0]);
|
||||
Serialization::load(buffer, type.tangentBasisComponents[1]);
|
||||
Serialization::load(buffer, type.tangentBasisComponents[2]);
|
||||
Serialization::load(buffer, type.textureCoordinates[0]);
|
||||
Serialization::load(buffer, type.textureCoordinates[1]);
|
||||
Serialization::load(buffer, type.textureCoordinates[2]);
|
||||
Serialization::load(buffer, type.textureCoordinates[3]);
|
||||
Serialization::load(buffer, type.colorComponent);
|
||||
}
|
||||
} // namespace Serialization
|
||||
} // namespace Seele
|
||||
@@ -6,6 +6,54 @@
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
void Seele::Serialization::save(ArchiveBuffer& buffer, VertexStreamComponent& comp)
|
||||
{
|
||||
if (comp.vertexBuffer == nullptr)
|
||||
{
|
||||
Serialization::save(buffer, (uint32)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serialization::save(buffer, comp.vertexBuffer->getNumVertices());
|
||||
Serialization::save(buffer, comp.vertexBuffer->getVertexSize());
|
||||
Array<uint8> rawBuffer;
|
||||
comp.vertexBuffer->download(rawBuffer);
|
||||
Serialization::save(buffer, rawBuffer);
|
||||
Serialization::save(buffer, comp.streamOffset);
|
||||
Serialization::save(buffer, comp.offset);
|
||||
Serialization::save(buffer, comp.stride);
|
||||
Serialization::save(buffer, comp.type);
|
||||
}
|
||||
}
|
||||
void Seele::Serialization::load(ArchiveBuffer& buffer, VertexStreamComponent& comp)
|
||||
{
|
||||
uint32 numVertices;
|
||||
Serialization::load(buffer, numVertices);
|
||||
if (numVertices == 0)
|
||||
{
|
||||
comp.vertexBuffer = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 vertexSize;
|
||||
Serialization::load(buffer, vertexSize);
|
||||
Array<uint8> rawBuffer;
|
||||
Serialization::load(buffer, rawBuffer);
|
||||
VertexBufferCreateInfo createInfo = {
|
||||
.resourceData = {
|
||||
.size = rawBuffer.size(),
|
||||
.data = rawBuffer.data(),
|
||||
},
|
||||
.vertexSize = vertexSize,
|
||||
.numVertices = numVertices,
|
||||
};
|
||||
comp.vertexBuffer = buffer.getGraphics()->createVertexBuffer(createInfo);
|
||||
Serialization::load(buffer, comp.streamOffset);
|
||||
Serialization::load(buffer, comp.offset);
|
||||
Serialization::load(buffer, comp.stride);
|
||||
Serialization::load(buffer, comp.type);
|
||||
}
|
||||
}
|
||||
|
||||
List<VertexInputType*>& VertexInputType::getTypeList()
|
||||
{
|
||||
@@ -90,7 +138,6 @@ Gfx::VertexElement VertexShaderInput::accessStreamComponent(const VertexStreamCo
|
||||
{
|
||||
VertexStream vertexStream;
|
||||
vertexStream.vertexBuffer = component.vertexBuffer;
|
||||
assert(component.stride < UINT8_MAX && component.offset < UINT8_MAX && component.offset < UINT8_MAX);
|
||||
vertexStream.stride = static_cast<uint8>(component.stride);
|
||||
vertexStream.offset = static_cast<uint8>(component.offset);
|
||||
|
||||
@@ -101,7 +148,6 @@ Gfx::VertexElement VertexShaderInput::accessPositionStreamComponent(const Vertex
|
||||
{
|
||||
VertexStream vertexStream;
|
||||
vertexStream.vertexBuffer = component.vertexBuffer;
|
||||
assert(component.stride < UINT8_MAX && component.offset < UINT8_MAX && component.offset < UINT8_MAX);
|
||||
vertexStream.stride = static_cast<uint8>(component.stride);
|
||||
vertexStream.offset = static_cast<uint8>(component.offset);
|
||||
|
||||
@@ -116,4 +162,4 @@ void VertexShaderInput::initDeclaration(Gfx::PGraphics graphics, Array<Gfx::Vert
|
||||
void VertexShaderInput::initPositionDeclaration(Gfx::PGraphics graphics, const Array<Gfx::VertexElement>& elements)
|
||||
{
|
||||
positionDeclaration = graphics->createVertexDeclaration(elements);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "MinimalEngine.h"
|
||||
#include "GraphicsEnums.h"
|
||||
#include "GraphicsResources.h"
|
||||
#include "Serialization/ArchiveBuffer.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
@@ -75,8 +76,11 @@ struct VertexStreamComponent
|
||||
{}
|
||||
};
|
||||
|
||||
#define STRUCTMEMBER_VERTEXSTREAMCOMPONENT(vertexBuffer, vertexType, member, memberType) \
|
||||
VertexStreamComponent(vertexBuffer, offsetof(vertexType, member), sizeof(vertexType), memberType)
|
||||
namespace Serialization
|
||||
{
|
||||
void save(ArchiveBuffer& buffer, VertexStreamComponent& comp);
|
||||
void load(ArchiveBuffer& buffer, VertexStreamComponent& comp);
|
||||
} // namespace Serialization
|
||||
|
||||
class VertexInputType
|
||||
{
|
||||
@@ -120,6 +124,8 @@ public:
|
||||
void getPositionOnlyStream(VertexInputStreamArray& outVertexStreams) const;
|
||||
virtual bool supportsTesselation() { return false; }
|
||||
virtual VertexInputType* getType() const { return nullptr; }
|
||||
virtual void save(ArchiveBuffer& buffer) {}
|
||||
virtual void load(ArchiveBuffer& buffer) {}
|
||||
Gfx::PVertexDeclaration getDeclaration() const {return declaration;}
|
||||
Gfx::PVertexDeclaration getPositionDeclaration() const {return positionDeclaration;}
|
||||
std::string getName() const { return name; }
|
||||
|
||||
@@ -182,7 +182,7 @@ void Allocation::markFree(SubAllocation *allocation)
|
||||
|
||||
if (allocHandle == nullptr)
|
||||
{
|
||||
allocHandle = new SubAllocation(this, allocation->alignedOffset, allocation->size, allocation->alignedOffset, allocation->allocatedSize);
|
||||
allocHandle = new SubAllocation(this, allocation->allocatedOffset, allocation->size, allocation->alignedOffset, allocation->allocatedSize);
|
||||
freeRanges[allocation->allocatedOffset] = allocHandle;
|
||||
}
|
||||
activeAllocations.erase(allocation->allocatedOffset);
|
||||
@@ -226,8 +226,7 @@ PSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2
|
||||
{
|
||||
std::scoped_lock lck(lock);
|
||||
const VkMemoryRequirements &requirements = memRequirements2.memoryRequirements;
|
||||
uint8 memoryTypeIndex;
|
||||
VK_CHECK(findMemoryType(requirements.memoryTypeBits, properties, &memoryTypeIndex));
|
||||
uint32 memoryTypeIndex = findMemoryType(requirements.memoryTypeBits, properties);
|
||||
uint32 heapIndex = memProperties.memoryTypes[memoryTypeIndex].heapIndex;
|
||||
|
||||
if (memRequirements2.pNext != nullptr)
|
||||
@@ -243,10 +242,13 @@ PSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2
|
||||
}
|
||||
for (auto alloc : heaps[heapIndex].allocations)
|
||||
{
|
||||
PSubAllocation suballoc = alloc->getSuballocation(requirements.size, requirements.alignment);
|
||||
if (suballoc != nullptr)
|
||||
if(alloc->memoryTypeIndex == memoryTypeIndex)
|
||||
{
|
||||
return suballoc;
|
||||
PSubAllocation suballoc = alloc->getSuballocation(requirements.size, requirements.alignment);
|
||||
if (suballoc != nullptr)
|
||||
{
|
||||
return suballoc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,22 +275,17 @@ void Allocator::free(Allocation *allocation)
|
||||
}
|
||||
}
|
||||
}
|
||||
VkResult Allocator::findMemoryType(uint32 typeBits, VkMemoryPropertyFlags properties, uint8 *typeIndex)
|
||||
uint32 Allocator::findMemoryType(uint32 typeFilter, VkMemoryPropertyFlags properties)
|
||||
{
|
||||
for (uint8 memoryIndex = 0; memoryIndex < memProperties.memoryTypeCount && typeBits; ++memoryIndex)
|
||||
for (uint32 i = 0; i < memProperties.memoryTypeCount; i++)
|
||||
{
|
||||
if ((typeBits & 1) == 1)
|
||||
if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties)
|
||||
{
|
||||
if ((memProperties.memoryTypes[memoryIndex].propertyFlags & properties) == properties)
|
||||
{
|
||||
*typeIndex = memoryIndex;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
typeBits >>= 1;
|
||||
}
|
||||
|
||||
return VK_ERROR_FORMAT_NOT_SUPPORTED;
|
||||
throw std::runtime_error("error finding memory");
|
||||
}
|
||||
|
||||
StagingBuffer::StagingBuffer()
|
||||
|
||||
@@ -155,7 +155,7 @@ private:
|
||||
Array<PAllocation> allocations;
|
||||
};
|
||||
Array<HeapInfo> heaps;
|
||||
VkResult findMemoryType(uint32 typeBits, VkMemoryPropertyFlags properties, uint8 *typeIndex);
|
||||
uint32 findMemoryType(uint32 typeBits, VkMemoryPropertyFlags properties);
|
||||
std::mutex lock;
|
||||
PGraphics graphics;
|
||||
VkPhysicalDeviceMemoryProperties memProperties;
|
||||
|
||||
@@ -208,7 +208,6 @@ void *ShaderBuffer::lockRegion(uint64 regionOffset, uint64 regionSize, bool bWri
|
||||
else
|
||||
{
|
||||
PCmdBuffer current = graphics->getQueueCommands(owner)->getCommands();
|
||||
graphics->getQueueCommands(owner)->submitCommands();
|
||||
current->waitForCommand();
|
||||
|
||||
requestOwnershipTransfer(Gfx::QueueType::DEDICATED_TRANSFER);
|
||||
@@ -466,6 +465,13 @@ void VertexBuffer::updateRegion(BulkResourceData update)
|
||||
unlock();
|
||||
}
|
||||
|
||||
void VertexBuffer::download(Array<uint8>& buffer)
|
||||
{
|
||||
void* data = lock(false);
|
||||
buffer.resize(size);
|
||||
std::memcpy(buffer.data(), data, size);
|
||||
unlock();
|
||||
}
|
||||
|
||||
void VertexBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner)
|
||||
{
|
||||
@@ -509,6 +515,14 @@ IndexBuffer::~IndexBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
void IndexBuffer::download(Array<uint8>& buffer)
|
||||
{
|
||||
void* data = lock(false);
|
||||
buffer.resize(size);
|
||||
std::memcpy(buffer.data(), data, size);
|
||||
unlock();
|
||||
}
|
||||
|
||||
void IndexBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner)
|
||||
{
|
||||
Gfx::QueueOwnedResource::transferOwnership(newOwner);
|
||||
|
||||
@@ -166,7 +166,12 @@ void CmdBuffer::refreshFence()
|
||||
|
||||
void CmdBuffer::waitForCommand(uint32 timeout)
|
||||
{
|
||||
std::scoped_lock lock(handleLock);
|
||||
manager->submitCommands();
|
||||
if (state == State::InsideBegin)
|
||||
{
|
||||
// is already done
|
||||
return;
|
||||
}
|
||||
fence->wait(timeout);
|
||||
refreshFence();
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ private:
|
||||
PGraphics graphics;
|
||||
Array<VkDescriptorSetLayoutBinding> bindings;
|
||||
VkDescriptorSetLayout layoutHandle;
|
||||
std::string name;
|
||||
friend class DescriptorAllocator;
|
||||
};
|
||||
DEFINE_REF(DescriptorLayout)
|
||||
|
||||
@@ -501,7 +501,7 @@ void Graphics::createDevice(GraphicsInitializer initializer)
|
||||
numQueuesForFamily++;
|
||||
}
|
||||
}
|
||||
if ((currProps.queueFlags & VK_QUEUE_COMPUTE_BIT) == VK_QUEUE_COMPUTE_BIT)
|
||||
if (currProps.queueFlags & VK_QUEUE_COMPUTE_BIT)
|
||||
{
|
||||
if (computeQueueInfo.familyIndex == -1)
|
||||
{
|
||||
@@ -526,7 +526,7 @@ void Graphics::createDevice(GraphicsInitializer initializer)
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((currProps.queueFlags & VK_QUEUE_TRANSFER_BIT) == VK_QUEUE_TRANSFER_BIT)
|
||||
if (currProps.queueFlags & VK_QUEUE_TRANSFER_BIT)
|
||||
{
|
||||
if (transferQueueInfo.familyIndex == -1)
|
||||
{
|
||||
@@ -587,6 +587,7 @@ void Graphics::createDevice(GraphicsInitializer initializer)
|
||||
deviceInfo.ppEnabledExtensionNames = initializer.deviceExtensions.data();
|
||||
deviceInfo.enabledLayerCount = (uint32_t)initializer.layers.size();
|
||||
deviceInfo.ppEnabledLayerNames = initializer.layers.data();
|
||||
deviceInfo.pEnabledFeatures = &features;
|
||||
|
||||
VK_CHECK(vkCreateDevice(physicalDevice, &deviceInfo, nullptr, &handle));
|
||||
std::cout << "Vulkan handle: " << handle << std::endl;
|
||||
|
||||
@@ -68,7 +68,6 @@ public:
|
||||
virtual Gfx::PPipelineLayout createPipelineLayout(Gfx::PPipelineLayout baseLayout = nullptr) override;
|
||||
|
||||
virtual void copyTexture(Gfx::PTexture srcTexture, Gfx::PTexture dstTexture) override;
|
||||
|
||||
protected:
|
||||
Array<const char *> getRequiredExtensions();
|
||||
void initInstance(GraphicsInitializer initInfo);
|
||||
|
||||
@@ -170,7 +170,7 @@ public:
|
||||
virtual ~VertexBuffer();
|
||||
|
||||
virtual void updateRegion(BulkResourceData update) override;
|
||||
|
||||
virtual void download(Array<uint8>& buffer) override;
|
||||
protected:
|
||||
// Inherited via Vulkan::Buffer
|
||||
virtual VkAccessFlags getSourceAccessMask();
|
||||
@@ -189,6 +189,7 @@ public:
|
||||
IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &resourceData);
|
||||
virtual ~IndexBuffer();
|
||||
|
||||
virtual void download(Array<uint8>& buffer) override;
|
||||
protected:
|
||||
// Inherited via Vulkan::Buffer
|
||||
virtual VkAccessFlags getSourceAccessMask();
|
||||
@@ -248,6 +249,7 @@ public:
|
||||
void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
|
||||
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage);
|
||||
void changeLayout(Gfx::SeImageLayout newLayout);
|
||||
void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer);
|
||||
|
||||
private:
|
||||
//Updates via reference
|
||||
@@ -314,6 +316,7 @@ public:
|
||||
return textureHandle->getMipLevels();
|
||||
}
|
||||
virtual void changeLayout(Gfx::SeImageLayout newLayout) override;
|
||||
virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer) override;
|
||||
virtual void* getNativeHandle() override
|
||||
{
|
||||
return textureHandle;
|
||||
@@ -369,6 +372,7 @@ public:
|
||||
return textureHandle->getMipLevels();
|
||||
}
|
||||
virtual void changeLayout(Gfx::SeImageLayout newLayout) override;
|
||||
virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer) override;
|
||||
virtual void* getNativeHandle() override
|
||||
{
|
||||
return textureHandle;
|
||||
@@ -424,6 +428,7 @@ public:
|
||||
return textureHandle->getMipLevels();
|
||||
}
|
||||
virtual void changeLayout(Gfx::SeImageLayout newLayout) override;
|
||||
virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer) override;
|
||||
virtual void* getNativeHandle() override
|
||||
{
|
||||
return textureHandle;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "VulkanGraphicsEnums.h"
|
||||
#include "VulkanAllocator.h"
|
||||
#include "VulkanCommandBuffer.h"
|
||||
#include "Graphics/GraphicsEnums.h"
|
||||
#include <math.h>
|
||||
|
||||
using namespace Seele;
|
||||
@@ -127,7 +128,7 @@ TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType,
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.imageSubresource.mipLevel = 0;
|
||||
region.imageSubresource.baseArrayLayer = 0;
|
||||
region.imageSubresource.layerCount = layerCount;
|
||||
region.imageSubresource.layerCount = arrayCount * layerCount;
|
||||
|
||||
region.imageOffset = {0, 0, 0};
|
||||
region.imageExtent = {sizeX, sizeY, sizeZ};
|
||||
@@ -212,6 +213,35 @@ void TextureHandle::changeLayout(Gfx::SeImageLayout newLayout)
|
||||
layout = newLayout;
|
||||
}
|
||||
|
||||
void TextureHandle::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer)
|
||||
{
|
||||
uint64 imageSize = sizeX * sizeY * sizeZ * Gfx::getFormatInfo(format).blockSize;
|
||||
|
||||
PStagingBuffer stagingbuffer = graphics->getStagingManager()->allocateStagingBuffer(imageSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true);
|
||||
auto prevlayout = layout;
|
||||
changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||
PCmdBuffer cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands();
|
||||
Gfx::FormatCompatibilityInfo formatInfo = Gfx::getFormatInfo(format);
|
||||
VkBufferImageCopy region = {
|
||||
.bufferOffset = 0,
|
||||
.bufferRowLength = 0,
|
||||
.bufferImageHeight = 0,
|
||||
.imageSubresource = {
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.mipLevel = mipLevel,
|
||||
.baseArrayLayer = arrayLayer * layerCount + face,
|
||||
.layerCount = 1,
|
||||
},
|
||||
.imageOffset = { 0, 0, 0 },
|
||||
.imageExtent = { sizeX, sizeY, sizeZ },
|
||||
};
|
||||
vkCmdCopyImageToBuffer(cmdBuffer->getHandle(), image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stagingbuffer->getHandle(), 1, ®ion);
|
||||
changeLayout(prevlayout);
|
||||
buffer.resize(stagingbuffer->getSize());
|
||||
void* data = stagingbuffer->getMappedPointer();
|
||||
std::memcpy(buffer.data(), data, buffer.size());
|
||||
}
|
||||
|
||||
void TextureHandle::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||
{
|
||||
VkImageMemoryBarrier imageBarrier =
|
||||
@@ -307,6 +337,11 @@ void Texture2D::changeLayout(Gfx::SeImageLayout newLayout)
|
||||
textureHandle->changeLayout(newLayout);
|
||||
}
|
||||
|
||||
void Texture2D::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer)
|
||||
{
|
||||
textureHandle->download(mipLevel, arrayLayer, face, buffer);
|
||||
}
|
||||
|
||||
void Texture2D::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||
{
|
||||
textureHandle->executeOwnershipBarrier(newOwner);
|
||||
@@ -334,6 +369,10 @@ void Texture3D::changeLayout(Gfx::SeImageLayout newLayout)
|
||||
textureHandle->changeLayout(newLayout);
|
||||
}
|
||||
|
||||
void Texture3D::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer)
|
||||
{
|
||||
textureHandle->download(mipLevel, arrayLayer, face, buffer);
|
||||
}
|
||||
void Texture3D::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||
{
|
||||
textureHandle->executeOwnershipBarrier(newOwner);
|
||||
@@ -361,6 +400,10 @@ void TextureCube::changeLayout(Gfx::SeImageLayout newLayout)
|
||||
textureHandle->changeLayout(newLayout);
|
||||
}
|
||||
|
||||
void TextureCube::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer)
|
||||
{
|
||||
textureHandle->download(mipLevel, arrayLayer, face, buffer);
|
||||
}
|
||||
void TextureCube::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||
{
|
||||
textureHandle->executeOwnershipBarrier(newOwner);
|
||||
|
||||
Reference in New Issue
Block a user