Refactor Vertex Shader input vertex layout to use GPUVertexLayout defined on Vertex Buffer rather than Vertex Shader
#3044 #2667
This commit is contained in:
@@ -315,8 +315,6 @@ float3 GetParticlePosition(uint ParticleIndex)
|
||||
|
||||
// Vertex Shader function for Sprite Rendering
|
||||
META_VS(true, FEATURE_LEVEL_ES2)
|
||||
META_VS_IN_ELEMENT(POSITION, 0, R32G32_FLOAT, 0, 0, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(TEXCOORD, 0, R32G32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
|
||||
VertexOutput VS_Sprite(SpriteInput input, uint particleIndex : SV_InstanceID)
|
||||
{
|
||||
VertexOutput output;
|
||||
|
||||
@@ -319,8 +319,6 @@ struct TerrainVertexInput
|
||||
|
||||
// Vertex Shader function for terrain rendering
|
||||
META_VS(true, FEATURE_LEVEL_ES2)
|
||||
META_VS_IN_ELEMENT(TEXCOORD, 0, R32G32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(TEXCOORD, 1, R8G8B8A8_UNORM, 0, ALIGN, PER_VERTEX, 0, true)
|
||||
VertexOutput VS(TerrainVertexInput input)
|
||||
{
|
||||
VertexOutput output;
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
"Name": "Flax",
|
||||
"Version": {
|
||||
"Major": 1,
|
||||
"Minor": 9,
|
||||
"Minor": 10,
|
||||
"Revision": 0,
|
||||
"Build": 6606
|
||||
"Build": 6701
|
||||
},
|
||||
"Company": "Flax",
|
||||
"Copyright": "Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.",
|
||||
|
||||
@@ -69,7 +69,8 @@ namespace FlaxEditor.Gizmo
|
||||
if (_vertexBuffer == null)
|
||||
{
|
||||
_vertexBuffer = new GPUBuffer();
|
||||
var desc = GPUBufferDescription.Vertex(sizeof(Float3), 4);
|
||||
var layout = GPUVertexLayout.Get([new VertexElement(VertexElement.Types.Position, 0, 0, false, PixelFormat.R32G32B32_Float)]);
|
||||
var desc = GPUBufferDescription.Vertex(layout, sizeof(Float3), 4);
|
||||
_vertexBuffer.Init(ref desc);
|
||||
}
|
||||
if (_indexBuffer == null)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "Engine/Graphics/RenderTools.h"
|
||||
#include "Engine/Graphics/DynamicBuffer.h"
|
||||
#include "Engine/Graphics/Shaders/GPUConstantBuffer.h"
|
||||
#include "Engine/Graphics/Shaders/GPUVertexLayout.h"
|
||||
#include "Engine/Graphics/Shaders/GPUShader.h"
|
||||
#include "Engine/Animations/AnimationUtils.h"
|
||||
#include "Engine/Profiler/Profiler.h"
|
||||
@@ -689,7 +690,7 @@ void DebugDrawService::Update()
|
||||
|
||||
// Vertex buffer
|
||||
if (DebugDrawVB == nullptr)
|
||||
DebugDrawVB = New<DynamicVertexBuffer>((uint32)(DEBUG_DRAW_INITIAL_VB_CAPACITY * sizeof(Vertex)), (uint32)sizeof(Vertex), TEXT("DebugDraw.VB"));
|
||||
DebugDrawVB = New<DynamicVertexBuffer>((uint32)(DEBUG_DRAW_INITIAL_VB_CAPACITY * sizeof(Vertex)), (uint32)sizeof(Vertex), TEXT("DebugDraw.VB"), Vertex::GetLayout());
|
||||
}
|
||||
|
||||
void DebugDrawService::Dispose()
|
||||
@@ -710,6 +711,14 @@ void DebugDrawService::Dispose()
|
||||
DebugDrawShader = nullptr;
|
||||
}
|
||||
|
||||
GPUVertexLayout* DebugDraw::Vertex::GetLayout()
|
||||
{
|
||||
return GPUVertexLayout::Get({
|
||||
{ VertexElement::Types::Position, 0, 0, 0, PixelFormat::R32G32B32_Float },
|
||||
{ VertexElement::Types::Color, 0, 12, 0, PixelFormat::R8G8B8A8_UNorm },
|
||||
});
|
||||
}
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
void* DebugDraw::AllocateContext()
|
||||
|
||||
@@ -17,6 +17,7 @@ struct RenderContext;
|
||||
class GPUTextureView;
|
||||
class GPUContext;
|
||||
class GPUBuffer;
|
||||
class GPUVertexLayout;
|
||||
class RenderTask;
|
||||
class SceneRenderTask;
|
||||
class Actor;
|
||||
@@ -35,6 +36,8 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
|
||||
PACK_STRUCT(struct Vertex {
|
||||
Float3 Position;
|
||||
Color32 Color;
|
||||
|
||||
static GPUVertexLayout* GetLayout();
|
||||
});
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
@@ -67,9 +67,15 @@ void DynamicBuffer::Dispose()
|
||||
Data.Resize(0);
|
||||
}
|
||||
|
||||
void DynamicVertexBuffer::SetLayout(GPUVertexLayout* layout)
|
||||
{
|
||||
_layout = layout;
|
||||
SAFE_DELETE_GPU_RESOURCE(_buffer);
|
||||
}
|
||||
|
||||
void DynamicVertexBuffer::InitDesc(GPUBufferDescription& desc, int32 numElements)
|
||||
{
|
||||
desc = GPUBufferDescription::Vertex(_stride, numElements, GPUResourceUsage::Dynamic);
|
||||
desc = GPUBufferDescription::Vertex(_layout, _stride, numElements, GPUResourceUsage::Dynamic);
|
||||
}
|
||||
|
||||
void DynamicIndexBuffer::InitDesc(GPUBufferDescription& desc, int32 numElements)
|
||||
|
||||
@@ -127,6 +127,9 @@ protected:
|
||||
/// </summary>
|
||||
class FLAXENGINE_API DynamicVertexBuffer : public DynamicBuffer
|
||||
{
|
||||
private:
|
||||
GPUVertexLayout* _layout;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Init
|
||||
@@ -134,11 +137,16 @@ public:
|
||||
/// <param name="initialCapacity">Initial capacity of the buffer (in bytes)</param>
|
||||
/// <param name="stride">Stride in bytes</param>
|
||||
/// <param name="name">Buffer name</param>
|
||||
DynamicVertexBuffer(uint32 initialCapacity, uint32 stride, const String& name = String::Empty)
|
||||
/// <param name="layout">The vertex buffer layout.</param>
|
||||
DynamicVertexBuffer(uint32 initialCapacity, uint32 stride, const String& name = String::Empty, GPUVertexLayout* layout = nullptr)
|
||||
: DynamicBuffer(initialCapacity, stride, name)
|
||||
, _layout(layout)
|
||||
{
|
||||
}
|
||||
|
||||
// Sets the vertex buffer layout.
|
||||
void SetLayout(GPUVertexLayout* layout);
|
||||
|
||||
protected:
|
||||
// [DynamicBuffer]
|
||||
void InitDesc(GPUBufferDescription& desc, int32 numElements) override;
|
||||
|
||||
@@ -27,6 +27,7 @@ GPUBufferDescription GPUBufferDescription::Buffer(uint32 size, GPUBufferFlags fl
|
||||
desc.Format = format;
|
||||
desc.InitData = initData;
|
||||
desc.Usage = usage;
|
||||
desc.VertexLayout = nullptr;
|
||||
return desc;
|
||||
}
|
||||
|
||||
@@ -48,6 +49,32 @@ GPUBufferDescription GPUBufferDescription::Typed(const void* data, int32 count,
|
||||
return Buffer(count * stride, bufferFlags, viewFormat, data, stride, usage);
|
||||
}
|
||||
|
||||
GPUBufferDescription GPUBufferDescription::Vertex(GPUVertexLayout* layout, uint32 elementStride, uint32 elementsCount, const void* data)
|
||||
{
|
||||
GPUBufferDescription desc;
|
||||
desc.Size = elementsCount * elementStride;
|
||||
desc.Stride = elementStride;
|
||||
desc.Flags = GPUBufferFlags::VertexBuffer;
|
||||
desc.Format = PixelFormat::Unknown;
|
||||
desc.InitData = data;
|
||||
desc.Usage = GPUResourceUsage::Default;
|
||||
desc.VertexLayout = layout;
|
||||
return desc;
|
||||
}
|
||||
|
||||
GPUBufferDescription GPUBufferDescription::Vertex(GPUVertexLayout* layout, uint32 elementStride, uint32 elementsCount, GPUResourceUsage usage)
|
||||
{
|
||||
GPUBufferDescription desc;
|
||||
desc.Size = elementsCount * elementStride;
|
||||
desc.Stride = elementStride;
|
||||
desc.Flags = GPUBufferFlags::VertexBuffer;
|
||||
desc.Format = PixelFormat::Unknown;
|
||||
desc.InitData = nullptr;
|
||||
desc.Usage = GPUResourceUsage::Default;
|
||||
desc.VertexLayout = layout;
|
||||
return desc;
|
||||
}
|
||||
|
||||
void GPUBufferDescription::Clear()
|
||||
{
|
||||
Platform::MemoryClear(this, sizeof(GPUBufferDescription));
|
||||
@@ -78,7 +105,8 @@ bool GPUBufferDescription::Equals(const GPUBufferDescription& other) const
|
||||
&& Flags == other.Flags
|
||||
&& Format == other.Format
|
||||
&& Usage == other.Usage
|
||||
&& InitData == other.InitData;
|
||||
&& InitData == other.InitData
|
||||
&& VertexLayout == other.VertexLayout;
|
||||
}
|
||||
|
||||
String GPUBufferDescription::ToString() const
|
||||
@@ -98,6 +126,7 @@ uint32 GetHash(const GPUBufferDescription& key)
|
||||
hashCode = (hashCode * 397) ^ (uint32)key.Flags;
|
||||
hashCode = (hashCode * 397) ^ (uint32)key.Format;
|
||||
hashCode = (hashCode * 397) ^ (uint32)key.Usage;
|
||||
hashCode = (hashCode * 397) ^ GetHash(key.VertexLayout);
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@@ -129,11 +158,16 @@ bool GPUBuffer::Init(const GPUBufferDescription& desc)
|
||||
&& Math::IsInRange<uint32>(desc.Stride, 0, 1024));
|
||||
|
||||
// Validate description
|
||||
#if !BUILD_RELEASE
|
||||
#define GET_NAME() GetName()
|
||||
#else
|
||||
#define GET_NAME() TEXT("")
|
||||
#endif
|
||||
if (EnumHasAnyFlags(desc.Flags, GPUBufferFlags::Structured))
|
||||
{
|
||||
if (desc.Stride <= 0)
|
||||
{
|
||||
LOG(Warning, "Cannot create buffer. Element size cannot be less or equal 0 for structured buffer.");
|
||||
LOG(Warning, "Cannot create buffer '{}'. Element size cannot be less or equal 0 for structured buffer.", GET_NAME());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -141,10 +175,19 @@ bool GPUBuffer::Init(const GPUBufferDescription& desc)
|
||||
{
|
||||
if (desc.Format != PixelFormat::R32_Typeless)
|
||||
{
|
||||
LOG(Warning, "Cannot create buffer. Raw buffers must use format R32_Typeless.");
|
||||
LOG(Warning, "Cannot create buffer '{}'. Raw buffers must use format R32_Typeless.", GET_NAME());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (EnumHasAnyFlags(desc.Flags, GPUBufferFlags::VertexBuffer))
|
||||
{
|
||||
if (desc.VertexLayout == nullptr)
|
||||
{
|
||||
// [Deprecated in v1.10] Change this into an error as VertexLayout becomes a requirement when layout is no longer set in a vertex shader
|
||||
LOG(Warning, "Missing Vertex Layout in buffer '{}'. Vertex Buffers should provide layout information about contained vertex elements.", GET_NAME());
|
||||
}
|
||||
}
|
||||
#undef GET_NAME
|
||||
|
||||
// Release previous data
|
||||
ReleaseGPU();
|
||||
|
||||
@@ -85,6 +85,14 @@ public:
|
||||
return _desc.Flags;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets vertex elements layout used by vertex buffers only.
|
||||
/// </summary>
|
||||
API_PROPERTY() FORCE_INLINE GPUVertexLayout* GetVertexLayout() const
|
||||
{
|
||||
return _desc.VertexLayout;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if buffer is a staging buffer (supports CPU readback).
|
||||
/// </summary>
|
||||
|
||||
@@ -48,6 +48,7 @@ namespace FlaxEngine
|
||||
desc.Format = format;
|
||||
desc.InitData = initData;
|
||||
desc.Usage = usage;
|
||||
desc.VertexLayout = null;
|
||||
return desc;
|
||||
}
|
||||
|
||||
@@ -70,6 +71,7 @@ namespace FlaxEngine
|
||||
desc.Format = format;
|
||||
desc.InitData = initData;
|
||||
desc.Usage = usage;
|
||||
desc.VertexLayout = null;
|
||||
return desc;
|
||||
}
|
||||
|
||||
@@ -117,11 +119,55 @@ namespace FlaxEngine
|
||||
/// <summary>
|
||||
/// Creates vertex buffer description.
|
||||
/// </summary>
|
||||
/// <param name="layout">The vertex buffer layout.</param>
|
||||
/// <param name="elementStride">The element stride.</param>
|
||||
/// <param name="elementsCount">The elements count.</param>
|
||||
/// <param name="data">The data.</param>
|
||||
/// <returns>The buffer description.</returns>
|
||||
public static GPUBufferDescription Vertex(int elementStride, int elementsCount, IntPtr data)
|
||||
public static GPUBufferDescription Vertex(GPUVertexLayout layout, int elementStride, int elementsCount, IntPtr data)
|
||||
{
|
||||
GPUBufferDescription desc;
|
||||
desc.Size = (uint)(elementsCount * elementStride);
|
||||
desc.Stride = (uint)elementStride;
|
||||
desc.Flags = GPUBufferFlags.VertexBuffer;
|
||||
desc.Format = PixelFormat.Unknown;
|
||||
desc.InitData = data;
|
||||
desc.Usage = GPUResourceUsage.Default;
|
||||
desc.VertexLayout = layout;
|
||||
return desc;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates vertex buffer description.
|
||||
/// </summary>
|
||||
/// <param name="layout">The vertex buffer layout.</param>
|
||||
/// <param name="elementStride">The element stride.</param>
|
||||
/// <param name="elementsCount">The elements count.</param>
|
||||
/// <param name="usage">The usage mode.</param>
|
||||
/// <returns>The buffer description.</returns>
|
||||
public static GPUBufferDescription Vertex(GPUVertexLayout layout, int elementStride, int elementsCount, GPUResourceUsage usage = GPUResourceUsage.Default)
|
||||
{
|
||||
GPUBufferDescription desc;
|
||||
desc.Size = (uint)(elementsCount * elementStride);
|
||||
desc.Stride = (uint)elementStride;
|
||||
desc.Flags = GPUBufferFlags.VertexBuffer;
|
||||
desc.Format = PixelFormat.Unknown;
|
||||
desc.InitData = new IntPtr();
|
||||
desc.Usage = usage;
|
||||
desc.VertexLayout = layout;
|
||||
return desc;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates vertex buffer description.
|
||||
/// </summary>
|
||||
/// <param name="elementStride">The element stride.</param>
|
||||
/// <param name="elementsCount">The elements count.</param>
|
||||
/// <param name="data">The data.</param>
|
||||
/// <param name="layout">The vertex buffer layout.</param>
|
||||
/// <returns>The buffer description.</returns>
|
||||
[Obsolete("Use Vertex with vertex layout parameter instead")]
|
||||
public static GPUBufferDescription Vertex(int elementStride, int elementsCount, IntPtr data, GPUVertexLayout layout = null)
|
||||
{
|
||||
return Buffer(elementsCount * elementStride, GPUBufferFlags.VertexBuffer, PixelFormat.Unknown, data, elementStride, GPUResourceUsage.Default);
|
||||
}
|
||||
@@ -132,18 +178,22 @@ namespace FlaxEngine
|
||||
/// <param name="elementStride">The element stride.</param>
|
||||
/// <param name="elementsCount">The elements count.</param>
|
||||
/// <param name="usage">The usage mode.</param>
|
||||
/// <param name="layout">The vertex buffer layout.</param>
|
||||
/// <returns>The buffer description.</returns>
|
||||
public static GPUBufferDescription Vertex(int elementStride, int elementsCount, GPUResourceUsage usage = GPUResourceUsage.Default)
|
||||
[Obsolete("Use Vertex with vertex layout parameter instead")]
|
||||
public static GPUBufferDescription Vertex(int elementStride, int elementsCount, GPUResourceUsage usage = GPUResourceUsage.Default, GPUVertexLayout layout = null)
|
||||
{
|
||||
return Buffer(elementsCount * elementStride, GPUBufferFlags.VertexBuffer, PixelFormat.Unknown, new IntPtr(), elementStride, usage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates vertex buffer description.
|
||||
/// [Deprecated in v1.10]
|
||||
/// </summary>
|
||||
/// <param name="size">The size (in bytes).</param>
|
||||
/// <param name="usage">The usage mode.</param>
|
||||
/// <returns>The buffer description.</returns>
|
||||
[Obsolete("Use Vertex with separate vertex stride and count instead")]
|
||||
public static GPUBufferDescription Vertex(int size, GPUResourceUsage usage = GPUResourceUsage.Default)
|
||||
{
|
||||
return Buffer(size, GPUBufferFlags.VertexBuffer, PixelFormat.Unknown, new IntPtr(), 0, usage);
|
||||
@@ -190,7 +240,6 @@ namespace FlaxEngine
|
||||
var bufferFlags = GPUBufferFlags.Structured | GPUBufferFlags.ShaderResource;
|
||||
if (isUnorderedAccess)
|
||||
bufferFlags |= GPUBufferFlags.UnorderedAccess;
|
||||
|
||||
return Buffer(elementCount * elementSize, bufferFlags, PixelFormat.Unknown, new IntPtr(), elementSize);
|
||||
}
|
||||
|
||||
@@ -304,7 +353,8 @@ namespace FlaxEngine
|
||||
Flags == other.Flags &&
|
||||
Format == other.Format &&
|
||||
InitData.Equals(other.InitData) &&
|
||||
Usage == other.Usage;
|
||||
Usage == other.Usage &&
|
||||
VertexLayout == other.VertexLayout;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -324,6 +374,58 @@ namespace FlaxEngine
|
||||
hashCode = (hashCode * 397) ^ (int)Format;
|
||||
hashCode = (hashCode * 397) ^ InitData.GetHashCode();
|
||||
hashCode = (hashCode * 397) ^ (int)Usage;
|
||||
if (VertexLayout != null)
|
||||
hashCode = (hashCode * 397) ^ VertexLayout.GetHashCode();
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
partial struct VertexElement : IEquatable<VertexElement>
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates the vertex element description.
|
||||
/// </summary>
|
||||
/// <param name="type">Element type.</param>
|
||||
/// <param name="slot">Vertex buffer bind slot.</param>
|
||||
/// <param name="offset">Data byte offset.</param>
|
||||
/// <param name="perInstance">True if element data is instanced.</param>
|
||||
/// <param name="format">Data format.</param>
|
||||
public VertexElement(Types type, byte slot, byte offset, bool perInstance, PixelFormat format)
|
||||
{
|
||||
Type = type;
|
||||
Slot = slot;
|
||||
Offset = offset;
|
||||
PerInstance = (byte)(perInstance ? 1 : 0);
|
||||
Format = format;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Equals(VertexElement other)
|
||||
{
|
||||
return Type == other.Type &&
|
||||
Slot == other.Slot &&
|
||||
Offset == other.Offset &&
|
||||
PerInstance == other.PerInstance &&
|
||||
Format == other.Format;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is VertexElement other && Equals(other);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
var hashCode = (int)Type;
|
||||
hashCode = (hashCode * 397) ^ Slot;
|
||||
hashCode = (hashCode * 397) ^ Offset;
|
||||
hashCode = (hashCode * 397) ^ PerInstance;
|
||||
hashCode = (hashCode * 397) ^ (int)Format;
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include "Enums.h"
|
||||
#include "PixelFormat.h"
|
||||
|
||||
class GPUVertexLayout;
|
||||
|
||||
/// <summary>
|
||||
/// The GPU buffer usage flags.
|
||||
/// </summary>
|
||||
@@ -110,6 +112,11 @@ API_STRUCT() struct FLAXENGINE_API GPUBufferDescription
|
||||
/// </summary>
|
||||
API_FIELD() GPUResourceUsage Usage;
|
||||
|
||||
/// <summary>
|
||||
/// The vertex elements layout used by vertex buffers only.
|
||||
/// </summary>
|
||||
API_FIELD() GPUVertexLayout* VertexLayout;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Gets the number elements in the buffer.
|
||||
@@ -178,34 +185,57 @@ public:
|
||||
/// <summary>
|
||||
/// Creates vertex buffer description.
|
||||
/// </summary>
|
||||
/// <param name="layout">The vertex buffer layout.</param>
|
||||
/// <param name="elementStride">The element stride.</param>
|
||||
/// <param name="elementsCount">The elements count.</param>
|
||||
/// <param name="data">The data.</param>
|
||||
/// <returns>The buffer description.</returns>
|
||||
static GPUBufferDescription Vertex(int32 elementStride, int32 elementsCount, const void* data)
|
||||
static GPUBufferDescription Vertex(GPUVertexLayout* layout, uint32 elementStride, uint32 elementsCount, const void* data);
|
||||
|
||||
/// <summary>
|
||||
/// Creates vertex buffer description.
|
||||
/// </summary>
|
||||
/// <param name="layout">The vertex buffer layout.</param>
|
||||
/// <param name="elementStride">The element stride.</param>
|
||||
/// <param name="elementsCount">The elements count.</param>
|
||||
/// <param name="usage">The usage mode.</param>
|
||||
/// <returns>The buffer description.</returns>
|
||||
static GPUBufferDescription Vertex(GPUVertexLayout* layout, uint32 elementStride, uint32 elementsCount, GPUResourceUsage usage = GPUResourceUsage::Default);
|
||||
|
||||
/// <summary>
|
||||
/// Creates vertex buffer description.
|
||||
/// [Deprecated in v1.10]
|
||||
/// </summary>
|
||||
/// <param name="elementStride">The element stride.</param>
|
||||
/// <param name="elementsCount">The elements count.</param>
|
||||
/// <param name="data">The data.</param>
|
||||
/// <returns>The buffer description.</returns>
|
||||
DEPRECATED("Use Vertex with vertex layout parameter instead") static GPUBufferDescription Vertex(int32 elementStride, int32 elementsCount, const void* data)
|
||||
{
|
||||
return Buffer(elementsCount * elementStride, GPUBufferFlags::VertexBuffer, PixelFormat::Unknown, data, elementStride, GPUResourceUsage::Default);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates vertex buffer description.
|
||||
/// [Deprecated in v1.10]
|
||||
/// </summary>
|
||||
/// <param name="elementStride">The element stride.</param>
|
||||
/// <param name="elementsCount">The elements count.</param>
|
||||
/// <param name="usage">The usage mode.</param>
|
||||
/// <returns>The buffer description.</returns>
|
||||
static GPUBufferDescription Vertex(int32 elementStride, int32 elementsCount, GPUResourceUsage usage = GPUResourceUsage::Default)
|
||||
DEPRECATED("Use Vertex with vertex layout parameter instead") static GPUBufferDescription Vertex(int32 elementStride, int32 elementsCount, GPUResourceUsage usage = GPUResourceUsage::Default)
|
||||
{
|
||||
return Buffer(elementsCount * elementStride, GPUBufferFlags::VertexBuffer, PixelFormat::Unknown, nullptr, elementStride, usage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates vertex buffer description.
|
||||
/// [Deprecated in v1.10]
|
||||
/// </summary>
|
||||
/// <param name="size">The size (in bytes).</param>
|
||||
/// <param name="usage">The usage mode.</param>
|
||||
/// <returns>The buffer description.</returns>
|
||||
static GPUBufferDescription Vertex(int32 size, GPUResourceUsage usage = GPUResourceUsage::Default)
|
||||
DEPRECATED("Use Vertex with separate vertex stride and count instead") static GPUBufferDescription Vertex(int32 size, GPUResourceUsage usage = GPUResourceUsage::Default)
|
||||
{
|
||||
return Buffer(size, GPUBufferFlags::VertexBuffer, PixelFormat::Unknown, nullptr, 0, usage);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ class GPUResource;
|
||||
class GPUResourceView;
|
||||
class GPUTextureView;
|
||||
class GPUBufferView;
|
||||
class GPUVertexLayout;
|
||||
|
||||
// Gets the GPU texture view. Checks if pointer is not null and texture has one or more mip levels loaded.
|
||||
#define GET_TEXTURE_VIEW_SAFE(t) (t && t->ResidentMipLevels() > 0 ? t->View() : nullptr)
|
||||
@@ -404,7 +405,8 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="vertexBuffers">The array of vertex buffers to use.</param>
|
||||
/// <param name="vertexBuffersOffsets">The optional array of byte offsets from the vertex buffers begins. Can be used to offset the vertex data when reusing the same buffer allocation for multiple geometry objects.</param>
|
||||
API_FUNCTION() virtual void BindVB(const Span<GPUBuffer*>& vertexBuffers, const uint32* vertexBuffersOffsets = nullptr) = 0;
|
||||
/// <param name="vertexLayout">The optional vertex layout to use when passing data from vertex buffers to the vertex shader. If null, layout will be automatically extracted from vertex buffers combined.</param>
|
||||
API_FUNCTION() virtual void BindVB(const Span<GPUBuffer*>& vertexBuffers, const uint32* vertexBuffersOffsets = nullptr, GPUVertexLayout* vertexLayout = nullptr) = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Binds the index buffer to the pipeline.
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#include "Engine/Renderer/RenderList.h"
|
||||
#include "Engine/Scripting/Enums.h"
|
||||
|
||||
#include "Shaders/GPUVertexLayout.h"
|
||||
|
||||
GPUResourcePropertyBase::~GPUResourcePropertyBase()
|
||||
{
|
||||
const auto e = _resource;
|
||||
@@ -386,7 +388,11 @@ bool GPUDevice::LoadContent()
|
||||
};
|
||||
// @formatter:on
|
||||
_res->FullscreenTriangleVB = CreateBuffer(TEXT("QuadVB"));
|
||||
if (_res->FullscreenTriangleVB->Init(GPUBufferDescription::Vertex(sizeof(float) * 4, 3, vb)))
|
||||
auto layout = GPUVertexLayout::Get({
|
||||
{ VertexElement::Types::Position, 0, 0, 0, PixelFormat::R32G32_Float },
|
||||
{ VertexElement::Types::TexCoord, 0, 8, 0, PixelFormat::R32G32_Float },
|
||||
});
|
||||
if (_res->FullscreenTriangleVB->Init(GPUBufferDescription::Vertex(layout, 16, 3, vb)))
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "Engine/Graphics/GPUDevice.h"
|
||||
#include "Engine/Graphics/RenderTask.h"
|
||||
#include "Engine/Graphics/RenderTools.h"
|
||||
#include "Engine/Graphics/Shaders/GPUVertexLayout.h"
|
||||
#include "Engine/Profiler/ProfilerCPU.h"
|
||||
#include "Engine/Renderer/RenderList.h"
|
||||
#include "Engine/Scripting/ManagedCLR/MCore.h"
|
||||
@@ -21,6 +22,30 @@
|
||||
#include "Engine/Renderer/GBufferPass.h"
|
||||
#endif
|
||||
|
||||
GPUVertexLayout* VB0ElementType18::GetLayout()
|
||||
{
|
||||
return GPUVertexLayout::Get({
|
||||
{ VertexElement::Types::Position, 0, 0, 0, PixelFormat::R32G32B32_Float },
|
||||
});
|
||||
}
|
||||
|
||||
GPUVertexLayout* VB1ElementType18::GetLayout()
|
||||
{
|
||||
return GPUVertexLayout::Get({
|
||||
{ VertexElement::Types::TexCoord, 1, 0, 0, PixelFormat::R16G16_Float },
|
||||
{ VertexElement::Types::Normal, 1, 0, 0, PixelFormat::R10G10B10A2_UNorm },
|
||||
{ VertexElement::Types::Tangent, 1, 0, 0, PixelFormat::R10G10B10A2_UNorm },
|
||||
{ VertexElement::Types::TexCoord1, 1, 0, 0, PixelFormat::R16G16_Float },
|
||||
});
|
||||
}
|
||||
|
||||
GPUVertexLayout* VB2ElementType18::GetLayout()
|
||||
{
|
||||
return GPUVertexLayout::Get({
|
||||
{ VertexElement::Types::Color, 2, 0, 0, PixelFormat::R8G8B8A8_UNorm },
|
||||
});
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
template<typename IndexType>
|
||||
@@ -233,15 +258,15 @@ bool Mesh::Load(uint32 vertices, uint32 triangles, const void* vb0, const void*
|
||||
#define MESH_BUFFER_NAME(postfix) String::Empty
|
||||
#endif
|
||||
vertexBuffer0 = GPUDevice::Instance->CreateBuffer(MESH_BUFFER_NAME(".VB0"));
|
||||
if (vertexBuffer0->Init(GPUBufferDescription::Vertex(sizeof(VB0ElementType), vertices, vb0)))
|
||||
if (vertexBuffer0->Init(GPUBufferDescription::Vertex(VB0ElementType::GetLayout(), sizeof(VB0ElementType), vertices, vb0)))
|
||||
goto ERROR_LOAD_END;
|
||||
vertexBuffer1 = GPUDevice::Instance->CreateBuffer(MESH_BUFFER_NAME(".VB1"));
|
||||
if (vertexBuffer1->Init(GPUBufferDescription::Vertex(sizeof(VB1ElementType), vertices, vb1)))
|
||||
if (vertexBuffer1->Init(GPUBufferDescription::Vertex(VB1ElementType::GetLayout(), sizeof(VB1ElementType), vertices, vb1)))
|
||||
goto ERROR_LOAD_END;
|
||||
if (vb2)
|
||||
{
|
||||
vertexBuffer2 = GPUDevice::Instance->CreateBuffer(MESH_BUFFER_NAME(".VB2"));
|
||||
if (vertexBuffer2->Init(GPUBufferDescription::Vertex(sizeof(VB2ElementType), vertices, vb2)))
|
||||
if (vertexBuffer2->Init(GPUBufferDescription::Vertex(VB2ElementType::GetLayout(), sizeof(VB2ElementType), vertices, vb2)))
|
||||
goto ERROR_LOAD_END;
|
||||
}
|
||||
indexBuffer = GPUDevice::Instance->CreateBuffer(MESH_BUFFER_NAME(".IB"));
|
||||
|
||||
@@ -151,6 +151,7 @@ public:
|
||||
|
||||
/// <summary>
|
||||
/// Init from model vertices array
|
||||
/// [Deprecated on 28.04.2023, expires on 01.01.2024]
|
||||
/// </summary>
|
||||
/// <param name="vertices">Array of vertices</param>
|
||||
/// <param name="verticesCount">Amount of vertices</param>
|
||||
@@ -158,6 +159,7 @@ public:
|
||||
|
||||
/// <summary>
|
||||
/// Init from model vertices array
|
||||
/// [Deprecated on 28.04.2023, expires on 01.01.2024]
|
||||
/// </summary>
|
||||
/// <param name="vertices">Array of vertices</param>
|
||||
/// <param name="verticesCount">Amount of vertices</param>
|
||||
@@ -182,6 +184,7 @@ public:
|
||||
|
||||
/// <summary>
|
||||
/// Init from model vertices array
|
||||
/// [Deprecated on 28.04.2023, expires on 01.01.2024]
|
||||
/// </summary>
|
||||
/// <param name="vb0">Array of data for vertex buffer 0</param>
|
||||
/// <param name="vb1">Array of data for vertex buffer 1</param>
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "Engine/Graphics/GPUDevice.h"
|
||||
#include "Engine/Graphics/RenderTask.h"
|
||||
#include "Engine/Graphics/RenderTools.h"
|
||||
#include "Engine/Graphics/Shaders/GPUVertexLayout.h"
|
||||
#include "Engine/Level/Scene/Scene.h"
|
||||
#include "Engine/Renderer/RenderList.h"
|
||||
#include "Engine/Serialization/MemoryReadStream.h"
|
||||
@@ -18,6 +19,18 @@
|
||||
#include "Engine/Threading/Task.h"
|
||||
#include "Engine/Threading/Threading.h"
|
||||
|
||||
GPUVertexLayout* VB0SkinnedElementType2::GetLayout()
|
||||
{
|
||||
return GPUVertexLayout::Get({
|
||||
{ VertexElement::Types::Position, 0, 0, 0, PixelFormat::R32G32B32_Float },
|
||||
{ VertexElement::Types::TexCoord, 0, 0, 0, PixelFormat::R16G16_Float },
|
||||
{ VertexElement::Types::Normal, 0, 0, 0, PixelFormat::R10G10B10A2_UNorm },
|
||||
{ VertexElement::Types::Tangent, 0, 0, 0, PixelFormat::R10G10B10A2_UNorm },
|
||||
{ VertexElement::Types::BlendIndices, 0, 0, 0, PixelFormat::R8G8B8A8_UInt },
|
||||
{ VertexElement::Types::BlendWeight, 0, 0, 0, PixelFormat::R16G16B16A16_Float },
|
||||
});
|
||||
}
|
||||
|
||||
void SkeletonData::Swap(SkeletonData& other)
|
||||
{
|
||||
Nodes.Swap(other.Nodes);
|
||||
@@ -120,7 +133,7 @@ bool SkinnedMesh::Load(uint32 vertices, uint32 triangles, const void* vb0, const
|
||||
#else
|
||||
vertexBuffer = GPUDevice::Instance->CreateBuffer(String::Empty);
|
||||
#endif
|
||||
if (vertexBuffer->Init(GPUBufferDescription::Vertex(sizeof(VB0SkinnedElementType), vertices, vb0)))
|
||||
if (vertexBuffer->Init(GPUBufferDescription::Vertex(VB0SkinnedElementType::GetLayout(), sizeof(VB0SkinnedElementType), vertices, vb0)))
|
||||
goto ERROR_LOAD_END;
|
||||
|
||||
// Create index buffer
|
||||
|
||||
@@ -21,6 +21,7 @@ class Model;
|
||||
class SkinnedModel;
|
||||
class MeshDeformation;
|
||||
class GPUContext;
|
||||
class GPUVertexLayout;
|
||||
struct RenderView;
|
||||
|
||||
/// <summary>
|
||||
@@ -69,6 +70,7 @@ enum class MeshBufferType
|
||||
};
|
||||
|
||||
// Vertex structure for all models (versioned)
|
||||
// [Deprecated on 28.04.2023, expires on 01.01.2024]
|
||||
PACK_STRUCT(struct ModelVertex15
|
||||
{
|
||||
Float3 Position;
|
||||
@@ -77,6 +79,7 @@ PACK_STRUCT(struct ModelVertex15
|
||||
Float1010102 Tangent;
|
||||
});
|
||||
|
||||
// [Deprecated on 28.04.2023, expires on 01.01.2024]
|
||||
PACK_STRUCT(struct ModelVertex18
|
||||
{
|
||||
Float3 Position;
|
||||
@@ -86,6 +89,7 @@ PACK_STRUCT(struct ModelVertex18
|
||||
Half2 LightmapUVs;
|
||||
});
|
||||
|
||||
// [Deprecated in v1.10]
|
||||
PACK_STRUCT(struct ModelVertex19
|
||||
{
|
||||
Float3 Position;
|
||||
@@ -96,9 +100,10 @@ PACK_STRUCT(struct ModelVertex19
|
||||
Color32 Color;
|
||||
});
|
||||
|
||||
// [Deprecated in v1.10]
|
||||
typedef ModelVertex19 ModelVertex;
|
||||
|
||||
//
|
||||
// [Deprecated in v1.10]
|
||||
struct RawModelVertex
|
||||
{
|
||||
Float3 Position;
|
||||
@@ -111,11 +116,12 @@ struct RawModelVertex
|
||||
};
|
||||
|
||||
// For vertex data we use three buffers: one with positions, one with other attributes, and one with colors
|
||||
// [Deprecated on 28.04.2023, expires on 01.01.2024]
|
||||
PACK_STRUCT(struct VB0ElementType15
|
||||
{
|
||||
Float3 Position;
|
||||
});
|
||||
|
||||
// [Deprecated on 28.04.2023, expires on 01.01.2024]
|
||||
PACK_STRUCT(struct VB1ElementType15
|
||||
{
|
||||
Half2 TexCoord;
|
||||
@@ -123,30 +129,42 @@ PACK_STRUCT(struct VB1ElementType15
|
||||
Float1010102 Tangent;
|
||||
});
|
||||
|
||||
// [Deprecated in v1.10]
|
||||
PACK_STRUCT(struct VB0ElementType18
|
||||
{
|
||||
Float3 Position;
|
||||
|
||||
static GPUVertexLayout* GetLayout();
|
||||
});
|
||||
|
||||
// [Deprecated in v1.10]
|
||||
PACK_STRUCT(struct VB1ElementType18
|
||||
{
|
||||
Half2 TexCoord;
|
||||
Float1010102 Normal;
|
||||
Float1010102 Tangent;
|
||||
Half2 LightmapUVs;
|
||||
|
||||
static GPUVertexLayout* GetLayout();
|
||||
});
|
||||
|
||||
// [Deprecated in v1.10]
|
||||
PACK_STRUCT(struct VB2ElementType18
|
||||
{
|
||||
Color32 Color;
|
||||
|
||||
static GPUVertexLayout* GetLayout();
|
||||
});
|
||||
|
||||
// [Deprecated in v1.10]
|
||||
typedef VB0ElementType18 VB0ElementType;
|
||||
// [Deprecated in v1.10]
|
||||
typedef VB1ElementType18 VB1ElementType;
|
||||
// [Deprecated in v1.10]
|
||||
typedef VB2ElementType18 VB2ElementType;
|
||||
//
|
||||
|
||||
// Vertex structure for all skinned models (versioned)
|
||||
// [Deprecated in v1.10]
|
||||
PACK_STRUCT(struct SkinnedModelVertex1
|
||||
{
|
||||
Float3 Position;
|
||||
@@ -157,9 +175,10 @@ PACK_STRUCT(struct SkinnedModelVertex1
|
||||
Color32 BlendWeights;
|
||||
});
|
||||
|
||||
// [Deprecated in v1.10]
|
||||
typedef SkinnedModelVertex1 SkinnedModelVertex;
|
||||
|
||||
//
|
||||
// [Deprecated in v1.10]
|
||||
struct RawSkinnedModelVertex
|
||||
{
|
||||
Float3 Position;
|
||||
@@ -171,6 +190,7 @@ struct RawSkinnedModelVertex
|
||||
Float4 BlendWeights;
|
||||
};
|
||||
|
||||
// [Deprecated on 28.04.2023, expires on 01.01.2024]
|
||||
PACK_STRUCT(struct VB0SkinnedElementType1
|
||||
{
|
||||
Float3 Position;
|
||||
@@ -181,6 +201,7 @@ PACK_STRUCT(struct VB0SkinnedElementType1
|
||||
Color32 BlendWeights;
|
||||
});
|
||||
|
||||
// [Deprecated in v1.10]
|
||||
PACK_STRUCT(struct VB0SkinnedElementType2
|
||||
{
|
||||
Float3 Position;
|
||||
@@ -189,7 +210,9 @@ PACK_STRUCT(struct VB0SkinnedElementType2
|
||||
Float1010102 Tangent;
|
||||
Color32 BlendIndices;
|
||||
Half4 BlendWeights;
|
||||
|
||||
static GPUVertexLayout* GetLayout();
|
||||
});
|
||||
|
||||
// [Deprecated in v1.10]
|
||||
typedef VB0SkinnedElementType2 VB0SkinnedElementType;
|
||||
//
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "GPUConstantBuffer.h"
|
||||
#include "Engine/Core/Log.h"
|
||||
#include "Engine/Core/Math/Math.h"
|
||||
#include "Engine/Core/Types/Span.h"
|
||||
#include "Engine/Graphics/GPUDevice.h"
|
||||
#include "Engine/Graphics/Shaders/GPUVertexLayout.h"
|
||||
#include "Engine/Serialization/MemoryReadStream.h"
|
||||
@@ -23,11 +24,6 @@ void GPUShaderProgram::Init(const GPUShaderProgramInitializer& initializer)
|
||||
#endif
|
||||
}
|
||||
|
||||
GPUShaderProgramVS::~GPUShaderProgramVS()
|
||||
{
|
||||
SAFE_DELETE(Layout);
|
||||
}
|
||||
|
||||
GPUShader::GPUShader()
|
||||
: GPUResource(SpawnParams(Guid::New(), TypeInitializer))
|
||||
{
|
||||
@@ -77,15 +73,15 @@ bool GPUShader::Create(MemoryReadStream& stream)
|
||||
|
||||
for (int32 permutationIndex = 0; permutationIndex < permutationsCount; permutationIndex++)
|
||||
{
|
||||
// Load cache
|
||||
uint32 cacheSize;
|
||||
stream.ReadUint32(&cacheSize);
|
||||
if (cacheSize > stream.GetLength() - stream.GetPosition())
|
||||
// Load bytecode
|
||||
uint32 bytecodeSize;
|
||||
stream.ReadUint32(&bytecodeSize);
|
||||
if (bytecodeSize > stream.GetLength() - stream.GetPosition())
|
||||
{
|
||||
LOG(Warning, "Invalid shader cache size.");
|
||||
LOG(Warning, "Invalid shader bytecode size.");
|
||||
return true;
|
||||
}
|
||||
byte* cache = stream.Move<byte>(cacheSize);
|
||||
byte* bytecode = stream.Move<byte>(bytecodeSize);
|
||||
|
||||
// Read bindings
|
||||
stream.ReadBytes(&initializer.Bindings, sizeof(ShaderBindings));
|
||||
@@ -96,7 +92,7 @@ bool GPUShader::Create(MemoryReadStream& stream)
|
||||
LOG(Warning, "Failed to create {} Shader program '{}' ({}).", ::ToString(type), String(initializer.Name), name);
|
||||
continue;
|
||||
}
|
||||
GPUShaderProgram* shader = CreateGPUShaderProgram(type, initializer, cache, cacheSize, stream);
|
||||
GPUShaderProgram* shader = CreateGPUShaderProgram(type, initializer, Span<byte>(bytecode, bytecodeSize), stream);
|
||||
if (shader == nullptr)
|
||||
{
|
||||
#if !GPU_ALLOW_TESSELLATION_SHADERS
|
||||
@@ -181,6 +177,24 @@ GPUShaderProgram* GPUShader::GetShader(ShaderStage stage, const StringAnsiView&
|
||||
return shader;
|
||||
}
|
||||
|
||||
GPUVertexLayout* GPUShader::ReadVertexLayout(MemoryReadStream& stream)
|
||||
{
|
||||
// [Deprecated in v1.10]
|
||||
byte inputLayoutSize;
|
||||
stream.ReadByte(&inputLayoutSize);
|
||||
if (inputLayoutSize == 0)
|
||||
return nullptr;
|
||||
void* elementsData = stream.Move(sizeof(VertexElement) * inputLayoutSize);
|
||||
if (inputLayoutSize > GPU_MAX_VS_ELEMENTS)
|
||||
{
|
||||
LOG(Error, "Incorrect input layout size.");
|
||||
return nullptr;
|
||||
}
|
||||
GPUVertexLayout::Elements elements;
|
||||
elements.Set((VertexElement*)elementsData, inputLayoutSize);
|
||||
return GPUVertexLayout::Get(elements);
|
||||
}
|
||||
|
||||
GPUResourceType GPUShader::GetResourceType() const
|
||||
{
|
||||
return GPUResourceType::Shader;
|
||||
|
||||
@@ -12,7 +12,7 @@ class GPUShaderProgram;
|
||||
/// <summary>
|
||||
/// The runtime version of the shaders cache supported by the all graphics back-ends. The same for all the shader cache formats (easier to sync and validate).
|
||||
/// </summary>
|
||||
#define GPU_SHADER_CACHE_VERSION 10
|
||||
#define GPU_SHADER_CACHE_VERSION 11
|
||||
|
||||
/// <summary>
|
||||
/// The GPU resource with shader programs that can run on the GPU and are able to perform rendering calculation using textures, vertices and other resources.
|
||||
@@ -134,7 +134,8 @@ public:
|
||||
|
||||
protected:
|
||||
GPUShaderProgram* GetShader(ShaderStage stage, const StringAnsiView& name, int32 permutationIndex) const;
|
||||
virtual GPUShaderProgram* CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, byte* cacheBytes, uint32 cacheSize, MemoryReadStream& stream) = 0;
|
||||
virtual GPUShaderProgram* CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, Span<byte> bytecode, MemoryReadStream& stream) = 0;
|
||||
static GPUVertexLayout* ReadVertexLayout(MemoryReadStream& stream);
|
||||
|
||||
public:
|
||||
// [GPUResource]
|
||||
|
||||
@@ -115,20 +115,11 @@ public:
|
||||
/// </summary>
|
||||
class GPUShaderProgramVS : public GPUShaderProgram
|
||||
{
|
||||
public:
|
||||
~GPUShaderProgramVS();
|
||||
|
||||
// Vertex elements input layout defined explicitly in the shader.
|
||||
// It's optional as it's been deprecated in favor or layouts defined by vertex buffers to allow data customizations.
|
||||
// Can be overriden by the vertex buffers provided upon draw call.
|
||||
// [Deprecated in v1.10]
|
||||
GPUVertexLayout* Layout = nullptr;
|
||||
|
||||
public:
|
||||
// Input element run-time data (see VertexShaderMeta::InputElement for compile-time data)
|
||||
// [Deprecated in v1.10]
|
||||
// [Deprecated in v1.10] Use VertexElement instead.
|
||||
PACK_STRUCT(struct InputElement
|
||||
{
|
||||
{
|
||||
byte Type; // VertexShaderMeta::InputType
|
||||
byte Index;
|
||||
byte Format; // PixelFormat
|
||||
@@ -136,19 +127,14 @@ public:
|
||||
uint32 AlignedByteOffset; // Fixed value or INPUT_LAYOUT_ELEMENT_ALIGN if auto
|
||||
byte InputSlotClass; // INPUT_LAYOUT_ELEMENT_PER_VERTEX_DATA or INPUT_LAYOUT_ELEMENT_PER_INSTANCE_DATA
|
||||
uint32 InstanceDataStepRate; // 0 if per-vertex
|
||||
});
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Gets input layout description handle (platform dependent).
|
||||
/// [Deprecated in v1.10]
|
||||
/// </summary>
|
||||
virtual void* GetInputLayout() const = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets input layout description size (in bytes).
|
||||
/// [Deprecated in v1.10]
|
||||
/// </summary>
|
||||
virtual byte GetInputLayoutSize() const = 0;
|
||||
// Vertex elements input layout defined explicitly in the shader.
|
||||
// It's optional as it's been deprecated in favor or layouts defined by vertex buffers to allow data customizations.
|
||||
// Can be overriden by the vertex buffers provided upon draw call.
|
||||
// (don't release it as it's managed by GPUVertexLayout::Get)
|
||||
// [Deprecated in v1.10]
|
||||
GPUVertexLayout* Layout = nullptr;
|
||||
|
||||
public:
|
||||
// [GPUShaderProgram]
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
#include "Engine/Core/Log.h"
|
||||
#endif
|
||||
#include "Engine/Core/Collections/Dictionary.h"
|
||||
#include "Engine/Core/Types/Span.h"
|
||||
#include "Engine/Graphics/GPUDevice.h"
|
||||
#include "Engine/Graphics/GPUBuffer.h"
|
||||
#if GPU_ENABLE_RESOURCE_NAMING
|
||||
#include "Engine/Scripting/Enums.h"
|
||||
#endif
|
||||
@@ -18,10 +20,29 @@ struct VertexElementRaw
|
||||
|
||||
static_assert(sizeof(VertexElement) == sizeof(VertexElementRaw), "Incorrect size of the VertexElement!");
|
||||
|
||||
struct VertexBufferLayouts
|
||||
{
|
||||
GPUVertexLayout* Layouts[GPU_MAX_VB_BINDED];
|
||||
|
||||
bool operator==(const VertexBufferLayouts& other) const
|
||||
{
|
||||
return Platform::MemoryCompare(&Layouts, &other.Layouts, sizeof(Layouts)) == 0;
|
||||
}
|
||||
};
|
||||
|
||||
uint32 GetHash(const VertexBufferLayouts& key)
|
||||
{
|
||||
uint32 hash = GetHash(key.Layouts[0]);
|
||||
for (int32 i = 1; i < GPU_MAX_VB_BINDED; i++)
|
||||
CombineHash(hash, GetHash(key.Layouts[i]));
|
||||
return hash;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
CriticalSection CacheLocker;
|
||||
Dictionary<uint32, GPUVertexLayout*> LayoutCache;
|
||||
Dictionary<VertexBufferLayouts, GPUVertexLayout*> VertexBufferCache;
|
||||
}
|
||||
|
||||
String VertexElement::ToString() const
|
||||
@@ -95,9 +116,50 @@ GPUVertexLayout* GPUVertexLayout::Get(const Elements& elements)
|
||||
return result;
|
||||
}
|
||||
|
||||
GPUVertexLayout* GPUVertexLayout::Get(const Span<GPUBuffer*>& vertexBuffers)
|
||||
{
|
||||
if (vertexBuffers.Length() == 0)
|
||||
return nullptr;
|
||||
if (vertexBuffers.Length() == 1)
|
||||
return vertexBuffers.Get()[0] ? vertexBuffers.Get()[0]->GetVertexLayout() : nullptr;
|
||||
|
||||
// Build hash key for set of buffers (in case there is layout sharing by different sets of buffers)
|
||||
VertexBufferLayouts layouts;
|
||||
for (int32 i = 0; i < vertexBuffers.Length(); i++)
|
||||
layouts.Layouts[i] = vertexBuffers.Get()[i] ? vertexBuffers.Get()[i]->GetVertexLayout() : nullptr;
|
||||
for (int32 i = vertexBuffers.Length(); i < GPU_MAX_VB_BINDED; i++)
|
||||
layouts.Layouts[i] = nullptr;
|
||||
|
||||
// Lookup existing cache
|
||||
CacheLocker.Lock();
|
||||
GPUVertexLayout* result;
|
||||
if (!VertexBufferCache.TryGet(layouts, result))
|
||||
{
|
||||
Elements elements;
|
||||
bool anyValid = false;
|
||||
for (int32 slot = 0; slot < vertexBuffers.Length(); slot++)
|
||||
{
|
||||
if (layouts.Layouts[slot])
|
||||
{
|
||||
anyValid = true;
|
||||
int32 start = elements.Count();
|
||||
elements.Add(layouts.Layouts[slot]->GetElements());
|
||||
for (int32 j = start; j < elements.Count() ;j++)
|
||||
elements.Get()[j].Slot = (byte)slot;
|
||||
}
|
||||
}
|
||||
result = anyValid ? Get(elements) : nullptr;
|
||||
VertexBufferCache.Add(layouts, result);
|
||||
}
|
||||
CacheLocker.Unlock();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void ClearVertexLayoutCache()
|
||||
{
|
||||
for (const auto& e : LayoutCache)
|
||||
Delete(e.Value);
|
||||
LayoutCache.Clear();
|
||||
VertexBufferCache.Clear();
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "Engine/Graphics/GPUResource.h"
|
||||
#include "Engine/Core/Collections/Array.h"
|
||||
|
||||
class GPUBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// Defines input layout of vertex buffer data passed to the Vertex Shader.
|
||||
/// </summary>
|
||||
@@ -35,6 +37,13 @@ public:
|
||||
/// <returns>Vertex layout object. Doesn't need to be cleared as it's cached for an application lifetime.</returns>
|
||||
API_FUNCTION() static GPUVertexLayout* Get(const Array<VertexElement, FixedAllocation<GPU_MAX_VS_ELEMENTS>>& elements);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the vertex layout for a given list of vertex buffers (sequence of binding slots based on layouts set on those buffers). Uses internal cache to skip creating layout if it's already exists for a given list.
|
||||
/// </summary>
|
||||
/// <param name="vertexBuffers">The list of vertex buffers for the layout.</param>
|
||||
/// <returns>Vertex layout object. Doesn't need to be cleared as it's cached for an application lifetime.</returns>
|
||||
API_FUNCTION() static GPUVertexLayout* Get(const Span<GPUBuffer*>& vertexBuffers);
|
||||
|
||||
public:
|
||||
// [GPUResource]
|
||||
GPUResourceType GetResourceType() const override
|
||||
|
||||
@@ -63,15 +63,15 @@ PACK_BEGIN() struct FLAXENGINE_API VertexElement
|
||||
};
|
||||
|
||||
// Type of the vertex element data.
|
||||
Types Type;
|
||||
API_FIELD() Types Type;
|
||||
// Index of the input vertex buffer slot (as provided in GPUContext::BindVB).
|
||||
byte Slot;
|
||||
API_FIELD() byte Slot;
|
||||
// Byte offset of this element relative to the start of a vertex buffer. Use value 0 to use auto-calculated offset based on previous elements in the layout (or for the first one).
|
||||
byte Offset;
|
||||
API_FIELD() byte Offset;
|
||||
// Flag used to mark data using hardware-instancing (element will be repeated for every instance). Empty to step data per-vertex when reading input buffer stream (rather than per-instance step).
|
||||
byte PerInstance;
|
||||
API_FIELD() byte PerInstance;
|
||||
// Format of the vertex element data.
|
||||
PixelFormat Format;
|
||||
API_FIELD() PixelFormat Format;
|
||||
|
||||
String ToString() const;
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "GPUTextureDX11.h"
|
||||
#include "GPUBufferDX11.h"
|
||||
#include "GPUSamplerDX11.h"
|
||||
#include "GPUVertexLayoutDX11.h"
|
||||
#include "Engine/GraphicsDevice/DirectX/RenderToolsDX.h"
|
||||
#include "Engine/Core/Math/Viewport.h"
|
||||
#include "Engine/Core/Math/Rectangle.h"
|
||||
@@ -82,9 +83,11 @@ void GPUContextDX11::FrameBegin()
|
||||
_omDirtyFlag = false;
|
||||
_uaDirtyFlag = false;
|
||||
_cbDirtyFlag = false;
|
||||
_iaInputLayoutDirtyFlag = false;
|
||||
_srMaskDirtyGraphics = 0;
|
||||
_srMaskDirtyCompute = 0;
|
||||
_rtCount = 0;
|
||||
_vertexLayout = nullptr;
|
||||
_currentState = nullptr;
|
||||
_rtDepth = nullptr;
|
||||
Platform::MemoryClear(_rtHandles, sizeof(_rtHandles));
|
||||
@@ -380,7 +383,7 @@ void GPUContextDX11::BindUA(int32 slot, GPUResourceView* view)
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextDX11::BindVB(const Span<GPUBuffer*>& vertexBuffers, const uint32* vertexBuffersOffsets)
|
||||
void GPUContextDX11::BindVB(const Span<GPUBuffer*>& vertexBuffers, const uint32* vertexBuffersOffsets, GPUVertexLayout* vertexLayout)
|
||||
{
|
||||
ASSERT(vertexBuffers.Length() >= 0 && vertexBuffers.Length() <= GPU_MAX_VB_BINDED);
|
||||
|
||||
@@ -402,6 +405,13 @@ void GPUContextDX11::BindVB(const Span<GPUBuffer*>& vertexBuffers, const uint32*
|
||||
{
|
||||
_context->IASetVertexBuffers(0, vertexBuffers.Length(), _vbHandles, _vbStrides, _vbOffsets);
|
||||
}
|
||||
if (!vertexLayout)
|
||||
vertexLayout = GPUVertexLayout::Get(vertexBuffers);
|
||||
if (_vertexLayout != vertexLayout)
|
||||
{
|
||||
_vertexLayout = (GPUVertexLayoutDX11*)vertexLayout;
|
||||
_iaInputLayoutDirtyFlag = true;
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextDX11::BindIB(GPUBuffer* indexBuffer)
|
||||
@@ -610,7 +620,7 @@ void GPUContextDX11::SetState(GPUPipelineState* state)
|
||||
#endif
|
||||
CurrentVS = vs;
|
||||
_context->VSSetShader(vs ? vs->GetBufferHandleDX11() : nullptr, nullptr, 0);
|
||||
_context->IASetInputLayout(vs ? vs->GetInputLayoutDX11() : nullptr);
|
||||
_iaInputLayoutDirtyFlag = true;
|
||||
}
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
if (CurrentHS != hs)
|
||||
@@ -720,6 +730,7 @@ void GPUContextDX11::FlushState()
|
||||
flushCBs();
|
||||
flushSRVs();
|
||||
flushUAVs();
|
||||
flushIA();
|
||||
flushOM();
|
||||
}
|
||||
|
||||
@@ -932,11 +943,28 @@ void GPUContextDX11::flushOM()
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextDX11::flushIA()
|
||||
{
|
||||
if (_iaInputLayoutDirtyFlag)
|
||||
{
|
||||
_iaInputLayoutDirtyFlag = false;
|
||||
ID3D11InputLayout* inputLayout = CurrentVS ? CurrentVS->GetInputLayout(_vertexLayout) : nullptr;
|
||||
#if GPU_ENABLE_ASSERTION_LOW_LAYERS
|
||||
if (!inputLayout && CurrentVS && !_vertexLayout && _vbHandles[0])
|
||||
{
|
||||
LOG(Error, "Missing Vertex Layout (not assigned to GPUBuffer). Vertex Shader won't read valid data resulting incorrect visuals.");
|
||||
}
|
||||
#endif
|
||||
_context->IASetInputLayout(inputLayout);
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextDX11::onDrawCall()
|
||||
{
|
||||
flushCBs();
|
||||
flushSRVs();
|
||||
flushUAVs();
|
||||
flushIA();
|
||||
flushOM();
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#if GRAPHICS_API_DIRECTX11
|
||||
|
||||
class GPUBufferDX11;
|
||||
class GPUVertexLayoutDX11;
|
||||
|
||||
/// <summary>
|
||||
/// GPU Context for DirectX 11 backend.
|
||||
@@ -49,6 +50,8 @@ private:
|
||||
ID3D11Buffer* _vbHandles[GPU_MAX_VB_BINDED];
|
||||
UINT _vbStrides[GPU_MAX_VB_BINDED];
|
||||
UINT _vbOffsets[GPU_MAX_VB_BINDED];
|
||||
GPUVertexLayoutDX11* _vertexLayout;
|
||||
bool _iaInputLayoutDirtyFlag;
|
||||
|
||||
// Pipeline State
|
||||
GPUPipelineStateDX11* _currentState;
|
||||
@@ -100,6 +103,7 @@ private:
|
||||
void flushUAVs();
|
||||
void flushCBs();
|
||||
void flushOM();
|
||||
void flushIA();
|
||||
void onDrawCall();
|
||||
|
||||
public:
|
||||
@@ -130,7 +134,7 @@ public:
|
||||
void BindCB(int32 slot, GPUConstantBuffer* cb) override;
|
||||
void BindSR(int32 slot, GPUResourceView* view) override;
|
||||
void BindUA(int32 slot, GPUResourceView* view) override;
|
||||
void BindVB(const Span<GPUBuffer*>& vertexBuffers, const uint32* vertexBuffersOffsets = nullptr) override;
|
||||
void BindVB(const Span<GPUBuffer*>& vertexBuffers, const uint32* vertexBuffersOffsets = nullptr, GPUVertexLayout* vertexLayout = nullptr) override;
|
||||
void BindIB(GPUBuffer* indexBuffer) override;
|
||||
void BindSampler(int32 slot, GPUSampler* sampler) override;
|
||||
void UpdateCB(GPUConstantBuffer* cb, const void* data) override;
|
||||
|
||||
@@ -4,10 +4,33 @@
|
||||
|
||||
#include "GPUShaderDX11.h"
|
||||
#include "GPUShaderProgramDX11.h"
|
||||
#include "GPUVertexLayoutDX11.h"
|
||||
#include "Engine/Serialization/MemoryReadStream.h"
|
||||
#include "../RenderToolsDX.h"
|
||||
|
||||
GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, byte* cacheBytes, uint32 cacheSize, MemoryReadStream& stream)
|
||||
GPUShaderProgramVSDX11::~GPUShaderProgramVSDX11()
|
||||
{
|
||||
for (const auto& e : _cache)
|
||||
e.Value->Release();
|
||||
}
|
||||
|
||||
ID3D11InputLayout* GPUShaderProgramVSDX11::GetInputLayout(GPUVertexLayoutDX11* vertexLayout)
|
||||
{
|
||||
if (!vertexLayout)
|
||||
vertexLayout = (GPUVertexLayoutDX11*)Layout;
|
||||
ID3D11InputLayout* inputLayout = nullptr;
|
||||
if (!_cache.TryGet(vertexLayout, inputLayout))
|
||||
{
|
||||
if (vertexLayout && vertexLayout->InputElementsCount)
|
||||
{
|
||||
VALIDATE_DIRECTX_CALL(vertexLayout->GetDevice()->GetDevice()->CreateInputLayout(vertexLayout->InputElements, vertexLayout->InputElementsCount, Bytecode.Get(), Bytecode.Length(), &inputLayout));
|
||||
}
|
||||
_cache.Add(vertexLayout, inputLayout);
|
||||
}
|
||||
return inputLayout;
|
||||
}
|
||||
|
||||
GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, Span<byte> bytecode, MemoryReadStream& stream)
|
||||
{
|
||||
GPUShaderProgram* shader = nullptr;
|
||||
HRESULT result;
|
||||
@@ -16,80 +39,15 @@ GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const
|
||||
case ShaderStage::Vertex:
|
||||
{
|
||||
// Load Input Layout
|
||||
byte inputLayoutSize;
|
||||
stream.ReadByte(&inputLayoutSize);
|
||||
ASSERT(inputLayoutSize <= VERTEX_SHADER_MAX_INPUT_ELEMENTS);
|
||||
D3D11_INPUT_ELEMENT_DESC inputLayoutDesc[VERTEX_SHADER_MAX_INPUT_ELEMENTS];
|
||||
for (int32 a = 0; a < inputLayoutSize; a++)
|
||||
{
|
||||
// Read description
|
||||
GPUShaderProgramVS::InputElement inputElement;
|
||||
stream.Read(inputElement);
|
||||
|
||||
// Get semantic name
|
||||
const char* semanticName = nullptr;
|
||||
// TODO: maybe use enum+mapping ?
|
||||
switch (inputElement.Type)
|
||||
{
|
||||
case 1:
|
||||
semanticName = "POSITION";
|
||||
break;
|
||||
case 2:
|
||||
semanticName = "COLOR";
|
||||
break;
|
||||
case 3:
|
||||
semanticName = "TEXCOORD";
|
||||
break;
|
||||
case 4:
|
||||
semanticName = "NORMAL";
|
||||
break;
|
||||
case 5:
|
||||
semanticName = "TANGENT";
|
||||
break;
|
||||
case 6:
|
||||
semanticName = "BITANGENT";
|
||||
break;
|
||||
case 7:
|
||||
semanticName = "ATTRIBUTE";
|
||||
break;
|
||||
case 8:
|
||||
semanticName = "BLENDINDICES";
|
||||
break;
|
||||
case 9:
|
||||
semanticName = "BLENDWEIGHT";
|
||||
break;
|
||||
default:
|
||||
LOG(Fatal, "Invalid vertex shader element semantic type: {0}", inputElement.Type);
|
||||
break;
|
||||
}
|
||||
|
||||
// Set data
|
||||
inputLayoutDesc[a] =
|
||||
{
|
||||
semanticName,
|
||||
static_cast<UINT>(inputElement.Index),
|
||||
static_cast<DXGI_FORMAT>(inputElement.Format),
|
||||
static_cast<UINT>(inputElement.InputSlot),
|
||||
static_cast<UINT>(inputElement.AlignedByteOffset),
|
||||
static_cast<D3D11_INPUT_CLASSIFICATION>(inputElement.InputSlotClass),
|
||||
static_cast<UINT>(inputElement.InstanceDataStepRate)
|
||||
};
|
||||
}
|
||||
|
||||
ID3D11InputLayout* inputLayout = nullptr;
|
||||
if (inputLayoutSize > 0)
|
||||
{
|
||||
// Create input layout
|
||||
VALIDATE_DIRECTX_CALL(_device->GetDevice()->CreateInputLayout(inputLayoutDesc, inputLayoutSize, cacheBytes, cacheSize, &inputLayout));
|
||||
}
|
||||
GPUVertexLayout* vertexLayout = ReadVertexLayout(stream);
|
||||
|
||||
// Create shader
|
||||
ID3D11VertexShader* buffer = nullptr;
|
||||
result = _device->GetDevice()->CreateVertexShader(cacheBytes, cacheSize, nullptr, &buffer);
|
||||
result = _device->GetDevice()->CreateVertexShader(bytecode.Get(), bytecode.Length(), nullptr, &buffer);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr);
|
||||
|
||||
// Create object
|
||||
shader = New<GPUShaderProgramVSDX11>(initializer, buffer, inputLayout, inputLayoutSize);
|
||||
shader = New<GPUShaderProgramVSDX11>(initializer, buffer, vertexLayout, bytecode);
|
||||
break;
|
||||
}
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
@@ -101,7 +59,7 @@ GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const
|
||||
|
||||
// Create shader
|
||||
ID3D11HullShader* buffer = nullptr;
|
||||
result = _device->GetDevice()->CreateHullShader(cacheBytes, cacheSize, nullptr, &buffer);
|
||||
result = _device->GetDevice()->CreateHullShader(bytecode.Get(), bytecode.Length(), nullptr, &buffer);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr);
|
||||
|
||||
// Create object
|
||||
@@ -112,7 +70,7 @@ GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const
|
||||
{
|
||||
// Create shader
|
||||
ID3D11DomainShader* buffer = nullptr;
|
||||
result = _device->GetDevice()->CreateDomainShader(cacheBytes, cacheSize, nullptr, &buffer);
|
||||
result = _device->GetDevice()->CreateDomainShader(bytecode.Get(), bytecode.Length(), nullptr, &buffer);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr);
|
||||
|
||||
// Create object
|
||||
@@ -132,7 +90,7 @@ GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const
|
||||
{
|
||||
// Create shader
|
||||
ID3D11GeometryShader* buffer = nullptr;
|
||||
result = _device->GetDevice()->CreateGeometryShader(cacheBytes, cacheSize, nullptr, &buffer);
|
||||
result = _device->GetDevice()->CreateGeometryShader(bytecode.Get(), bytecode.Length(), nullptr, &buffer);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr);
|
||||
|
||||
// Create object
|
||||
@@ -144,7 +102,7 @@ GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const
|
||||
{
|
||||
// Create shader
|
||||
ID3D11PixelShader* buffer = nullptr;
|
||||
result = _device->GetDevice()->CreatePixelShader(cacheBytes, cacheSize, nullptr, &buffer);
|
||||
result = _device->GetDevice()->CreatePixelShader(bytecode.Get(), bytecode.Length(), nullptr, &buffer);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr);
|
||||
|
||||
// Create object
|
||||
@@ -155,7 +113,7 @@ GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const
|
||||
{
|
||||
// Create shader
|
||||
ID3D11ComputeShader* buffer = nullptr;
|
||||
result = _device->GetDevice()->CreateComputeShader(cacheBytes, cacheSize, nullptr, &buffer);
|
||||
result = _device->GetDevice()->CreateComputeShader(bytecode.Get(), bytecode.Length(), nullptr, &buffer);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr);
|
||||
|
||||
// Create object
|
||||
|
||||
@@ -80,7 +80,7 @@ public:
|
||||
|
||||
protected:
|
||||
// [GPUShader]
|
||||
GPUShaderProgram* CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, byte* cacheBytes, uint32 cacheSize, MemoryReadStream& stream) override;
|
||||
GPUShaderProgram* CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, Span<byte> bytecode, MemoryReadStream& stream) override;
|
||||
void OnReleaseGPU() override;
|
||||
|
||||
public:
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "Engine/Graphics/Shaders/GPUShaderProgram.h"
|
||||
#include "Engine/Core/Types/DataContainer.h"
|
||||
#include "../IncludeDirectXHeaders.h"
|
||||
|
||||
#if GRAPHICS_API_DIRECTX11
|
||||
@@ -17,11 +18,6 @@ protected:
|
||||
BufferType* _buffer;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUShaderProgramDX11"/> class.
|
||||
/// </summary>
|
||||
/// <param name="initializer">The program initialization data.</param>
|
||||
/// <param name="buffer">The shader buffer object.</param>
|
||||
GPUShaderProgramDX11(const GPUShaderProgramInitializer& initializer, BufferType* buffer)
|
||||
: _buffer(buffer)
|
||||
{
|
||||
@@ -31,18 +27,11 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes an instance of the <see cref="GPUShaderProgramDX11"/> class.
|
||||
/// </summary>
|
||||
~GPUShaderProgramDX11()
|
||||
{
|
||||
DX_SAFE_RELEASE_CHECK(_buffer, 0);
|
||||
}
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Gets DirectX 11 buffer handle.
|
||||
/// </summary>
|
||||
FORCE_INLINE BufferType* GetBufferHandleDX11() const
|
||||
{
|
||||
return _buffer;
|
||||
@@ -66,51 +55,21 @@ public:
|
||||
class GPUShaderProgramVSDX11 : public GPUShaderProgramDX11<GPUShaderProgramVS, ID3D11VertexShader>
|
||||
{
|
||||
private:
|
||||
byte _inputLayoutSize;
|
||||
ID3D11InputLayout* _inputLayout;
|
||||
Dictionary<class GPUVertexLayoutDX11*, ID3D11InputLayout*> _cache;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUShaderProgramVSDX11"/> class.
|
||||
/// </summary>
|
||||
/// <param name="initializer">The program initialization data.</param>
|
||||
/// <param name="buffer">The shader buffer object.</param>
|
||||
/// <param name="inputLayout">The input layout.</param>
|
||||
/// <param name="inputLayoutSize">Size of the input layout.</param>
|
||||
GPUShaderProgramVSDX11(const GPUShaderProgramInitializer& initializer, ID3D11VertexShader* buffer, ID3D11InputLayout* inputLayout, byte inputLayoutSize)
|
||||
GPUShaderProgramVSDX11(const GPUShaderProgramInitializer& initializer, ID3D11VertexShader* buffer, GPUVertexLayout* vertexLayout, Span<byte> bytecode)
|
||||
: GPUShaderProgramDX11(initializer, buffer)
|
||||
, _inputLayoutSize(inputLayoutSize)
|
||||
, _inputLayout(inputLayout)
|
||||
{
|
||||
Layout = vertexLayout;
|
||||
Bytecode.Copy(bytecode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes an instance of the <see cref="GPUShaderProgramVSDX11"/> class.
|
||||
/// </summary>
|
||||
~GPUShaderProgramVSDX11()
|
||||
{
|
||||
DX_SAFE_RELEASE_CHECK(_inputLayout, 0);
|
||||
}
|
||||
~GPUShaderProgramVSDX11();
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Gets the DirectX 11 input layout handle
|
||||
/// </summary>
|
||||
FORCE_INLINE ID3D11InputLayout* GetInputLayoutDX11() const
|
||||
{
|
||||
return _inputLayout;
|
||||
}
|
||||
BytesContainer Bytecode;
|
||||
|
||||
public:
|
||||
// [GPUShaderProgramDX11]
|
||||
void* GetInputLayout() const override
|
||||
{
|
||||
return (void*)_inputLayout;
|
||||
}
|
||||
byte GetInputLayoutSize() const override
|
||||
{
|
||||
return _inputLayoutSize;
|
||||
}
|
||||
ID3D11InputLayout* GetInputLayout(class GPUVertexLayoutDX11* vertexLayout);
|
||||
};
|
||||
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
@@ -120,12 +79,6 @@ public:
|
||||
class GPUShaderProgramHSDX11 : public GPUShaderProgramDX11<GPUShaderProgramHS, ID3D11HullShader>
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUShaderProgramHSDX11"/> class.
|
||||
/// </summary>
|
||||
/// <param name="initializer">The program initialization data.</param>
|
||||
/// <param name="buffer">The shader buffer object.</param>
|
||||
/// <param name="controlPointsCount">The control points used by the hull shader for processing.</param>
|
||||
GPUShaderProgramHSDX11(const GPUShaderProgramInitializer& initializer, ID3D11HullShader* buffer, int32 controlPointsCount)
|
||||
: GPUShaderProgramDX11(initializer, buffer)
|
||||
{
|
||||
@@ -139,11 +92,6 @@ public:
|
||||
class GPUShaderProgramDSDX11 : public GPUShaderProgramDX11<GPUShaderProgramDS, ID3D11DomainShader>
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUShaderProgramDSDX11"/> class.
|
||||
/// </summary>
|
||||
/// <param name="initializer">The program initialization data.</param>
|
||||
/// <param name="buffer">The shader buffer object.</param>
|
||||
GPUShaderProgramDSDX11(const GPUShaderProgramInitializer& initializer, ID3D11DomainShader* buffer)
|
||||
: GPUShaderProgramDX11(initializer, buffer)
|
||||
{
|
||||
@@ -158,11 +106,6 @@ public:
|
||||
class GPUShaderProgramGSDX11 : public GPUShaderProgramDX11<GPUShaderProgramGS, ID3D11GeometryShader>
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUShaderProgramGSDX11"/> class.
|
||||
/// </summary>
|
||||
/// <param name="initializer">The program initialization data.</param>
|
||||
/// <param name="buffer">The shader buffer object.</param>
|
||||
GPUShaderProgramGSDX11(const GPUShaderProgramInitializer& initializer, ID3D11GeometryShader* buffer)
|
||||
: GPUShaderProgramDX11(initializer, buffer)
|
||||
{
|
||||
@@ -176,11 +119,6 @@ public:
|
||||
class GPUShaderProgramPSDX11 : public GPUShaderProgramDX11<GPUShaderProgramPS, ID3D11PixelShader>
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUShaderProgramPSDX11"/> class.
|
||||
/// </summary>
|
||||
/// <param name="initializer">The program initialization data.</param>
|
||||
/// <param name="buffer">The shader buffer object.</param>
|
||||
GPUShaderProgramPSDX11(const GPUShaderProgramInitializer& initializer, ID3D11PixelShader* buffer)
|
||||
: GPUShaderProgramDX11(initializer, buffer)
|
||||
{
|
||||
@@ -193,11 +131,6 @@ public:
|
||||
class GPUShaderProgramCSDX11 : public GPUShaderProgramDX11<GPUShaderProgramCS, ID3D11ComputeShader>
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUShaderProgramCSDX11"/> class.
|
||||
/// </summary>
|
||||
/// <param name="initializer">The program initialization data.</param>
|
||||
/// <param name="buffer">The shader buffer object.</param>
|
||||
GPUShaderProgramCSDX11(const GPUShaderProgramInitializer& initializer, ID3D11ComputeShader* buffer)
|
||||
: GPUShaderProgramDX11(initializer, buffer)
|
||||
{
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "GPUTextureDX12.h"
|
||||
#include "GPUBufferDX12.h"
|
||||
#include "GPUSamplerDX12.h"
|
||||
#include "GPUVertexLayoutDX12.h"
|
||||
#include "CommandQueueDX12.h"
|
||||
#include "DescriptorHeapDX12.h"
|
||||
#include "Engine/Graphics/RenderTask.h"
|
||||
@@ -244,6 +245,7 @@ void GPUContextDX12::Reset()
|
||||
Platform::MemoryClear(_srHandles, sizeof(_srHandles));
|
||||
Platform::MemoryClear(_uaHandles, sizeof(_uaHandles));
|
||||
Platform::MemoryClear(_vbHandles, sizeof(_vbHandles));
|
||||
_vertexLayout = nullptr;
|
||||
_ibHandle = nullptr;
|
||||
Platform::MemoryClear(&_cbHandles, sizeof(_cbHandles));
|
||||
Platform::MemoryClear(&_samplers, sizeof(_samplers));
|
||||
@@ -560,7 +562,13 @@ void GPUContextDX12::flushPS()
|
||||
|
||||
// Change state
|
||||
ASSERT(_currentState->IsValid());
|
||||
_commandList->SetPipelineState(_currentState->GetState(_rtDepth, _rtCount, _rtHandles));
|
||||
#if GPU_ENABLE_ASSERTION_LOW_LAYERS
|
||||
if (!_vertexLayout && _vbHandles[0] && !_currentState->VertexLayout)
|
||||
{
|
||||
LOG(Error, "Missing Vertex Layout (not assigned to GPUBuffer). Vertex Shader won't read valid data resulting incorrect visuals.");
|
||||
}
|
||||
#endif
|
||||
_commandList->SetPipelineState(_currentState->GetState(_rtDepth, _rtCount, _rtHandles, _vertexLayout));
|
||||
if (_primitiveTopology != _currentState->PrimitiveTopology)
|
||||
{
|
||||
_primitiveTopology = _currentState->PrimitiveTopology;
|
||||
@@ -946,7 +954,7 @@ void GPUContextDX12::BindUA(int32 slot, GPUResourceView* view)
|
||||
*view->LastRenderTime = _lastRenderTime;
|
||||
}
|
||||
|
||||
void GPUContextDX12::BindVB(const Span<GPUBuffer*>& vertexBuffers, const uint32* vertexBuffersOffsets)
|
||||
void GPUContextDX12::BindVB(const Span<GPUBuffer*>& vertexBuffers, const uint32* vertexBuffersOffsets, GPUVertexLayout* vertexLayout)
|
||||
{
|
||||
ASSERT(vertexBuffers.Length() >= 0 && vertexBuffers.Length() <= GPU_MAX_VB_BINDED);
|
||||
|
||||
@@ -982,6 +990,7 @@ void GPUContextDX12::BindVB(const Span<GPUBuffer*>& vertexBuffers, const uint32*
|
||||
#endif
|
||||
_commandList->IASetVertexBuffers(0, vertexBuffers.Length(), views);
|
||||
}
|
||||
_vertexLayout = (GPUVertexLayoutDX12*)(vertexLayout ? vertexLayout : GPUVertexLayout::Get(vertexBuffers));
|
||||
}
|
||||
|
||||
void GPUContextDX12::BindIB(GPUBuffer* indexBuffer)
|
||||
|
||||
@@ -15,6 +15,7 @@ class GPUBufferDX12;
|
||||
class GPUSamplerDX12;
|
||||
class GPUConstantBufferDX12;
|
||||
class GPUTextureViewDX12;
|
||||
class GPUVertexLayoutDX12;
|
||||
|
||||
/// <summary>
|
||||
/// Size of the resource barriers buffer size (will be flushed on overflow)
|
||||
@@ -61,6 +62,7 @@ private:
|
||||
GPUTextureViewDX12* _rtHandles[GPU_MAX_RT_BINDED];
|
||||
IShaderResourceDX12* _srHandles[GPU_MAX_SR_BINDED];
|
||||
IShaderResourceDX12* _uaHandles[GPU_MAX_UA_BINDED];
|
||||
GPUVertexLayoutDX12* _vertexLayout;
|
||||
GPUBufferDX12* _ibHandle;
|
||||
GPUBufferDX12* _vbHandles[GPU_MAX_VB_BINDED];
|
||||
D3D12_INDEX_BUFFER_VIEW _ibView;
|
||||
@@ -176,7 +178,7 @@ public:
|
||||
void BindCB(int32 slot, GPUConstantBuffer* cb) override;
|
||||
void BindSR(int32 slot, GPUResourceView* view) override;
|
||||
void BindUA(int32 slot, GPUResourceView* view) override;
|
||||
void BindVB(const Span<GPUBuffer*>& vertexBuffers, const uint32* vertexBuffersOffsets = nullptr) override;
|
||||
void BindVB(const Span<GPUBuffer*>& vertexBuffers, const uint32* vertexBuffersOffsets = nullptr, GPUVertexLayout* vertexLayout = nullptr) override;
|
||||
void BindIB(GPUBuffer* indexBuffer) override;
|
||||
void BindSampler(int32 slot, GPUSampler* sampler) override;
|
||||
void UpdateCB(GPUConstantBuffer* cb, const void* data) override;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "GPUPipelineStateDX12.h"
|
||||
#include "GPUShaderProgramDX12.h"
|
||||
#include "GPUVertexLayoutDX12.h"
|
||||
#include "GPUTextureDX12.h"
|
||||
#include "Engine/Profiler/ProfilerCPU.h"
|
||||
#include "Engine/GraphicsDevice/DirectX/RenderToolsDX.h"
|
||||
@@ -45,14 +46,16 @@ bool GPUPipelineStateDX12::IsValid() const
|
||||
return !!_memoryUsage;
|
||||
}
|
||||
|
||||
ID3D12PipelineState* GPUPipelineStateDX12::GetState(GPUTextureViewDX12* depth, int32 rtCount, GPUTextureViewDX12** rtHandles)
|
||||
ID3D12PipelineState* GPUPipelineStateDX12::GetState(GPUTextureViewDX12* depth, int32 rtCount, GPUTextureViewDX12** rtHandles, GPUVertexLayoutDX12* vertexLayout)
|
||||
{
|
||||
// Validate
|
||||
ASSERT(depth || rtCount);
|
||||
if (!vertexLayout)
|
||||
vertexLayout = VertexLayout;
|
||||
|
||||
// Prepare key
|
||||
GPUPipelineStateKeyDX12 key;
|
||||
key.RTsCount = rtCount;
|
||||
key.VertexLayout = vertexLayout;
|
||||
key.DepthFormat = depth ? depth->GetFormat() : PixelFormat::Unknown;
|
||||
key.MSAA = depth ? depth->GetMSAA() : (rtCount ? rtHandles[0]->GetMSAA() : MSAALevel::None);
|
||||
for (int32 i = 0; i < rtCount; i++)
|
||||
@@ -72,7 +75,6 @@ ID3D12PipelineState* GPUPipelineStateDX12::GetState(GPUTextureViewDX12* depth, i
|
||||
#endif
|
||||
return state;
|
||||
}
|
||||
|
||||
PROFILE_CPU_NAMED("Create Pipeline State");
|
||||
|
||||
// Update description to match the pipeline
|
||||
@@ -83,6 +85,8 @@ ID3D12PipelineState* GPUPipelineStateDX12::GetState(GPUTextureViewDX12* depth, i
|
||||
_desc.SampleDesc.Quality = key.MSAA == MSAALevel::None ? 0 : GPUDeviceDX12::GetMaxMSAAQuality((int32)key.MSAA);
|
||||
_desc.SampleMask = D3D12_DEFAULT_SAMPLE_MASK;
|
||||
_desc.DSVFormat = RenderToolsDX::ToDxgiFormat(PixelFormatExtensions::FindDepthStencilFormat(key.DepthFormat));
|
||||
_desc.InputLayout.pInputElementDescs = vertexLayout ? vertexLayout->InputElements : nullptr;
|
||||
_desc.InputLayout.NumElements = vertexLayout ? vertexLayout->InputElementsCount : 0;
|
||||
|
||||
// Create object
|
||||
const HRESULT result = _device->GetDevice()->CreateGraphicsPipelineState(&_desc, IID_PPV_ARGS(&state));
|
||||
@@ -96,6 +100,7 @@ ID3D12PipelineState* GPUPipelineStateDX12::GetState(GPUTextureViewDX12* depth, i
|
||||
name.Add(*DebugDesc.VS->GetName(), DebugDesc.VS->GetName().Length());
|
||||
name.Add('+');
|
||||
}
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
if (DebugDesc.HS)
|
||||
{
|
||||
name.Add(*DebugDesc.HS->GetName(), DebugDesc.HS->GetName().Length());
|
||||
@@ -106,11 +111,14 @@ ID3D12PipelineState* GPUPipelineStateDX12::GetState(GPUTextureViewDX12* depth, i
|
||||
name.Add(*DebugDesc.DS->GetName(), DebugDesc.DS->GetName().Length());
|
||||
name.Add('+');
|
||||
}
|
||||
#endif
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
if (DebugDesc.GS)
|
||||
{
|
||||
name.Add(*DebugDesc.GS->GetName(), DebugDesc.GS->GetName().Length());
|
||||
name.Add('+');
|
||||
}
|
||||
#endif
|
||||
if (DebugDesc.PS)
|
||||
{
|
||||
name.Add(*DebugDesc.PS->GetName(), DebugDesc.PS->GetName().Length());
|
||||
@@ -148,7 +156,6 @@ bool GPUPipelineStateDX12::Init(const Description& desc)
|
||||
|
||||
// Shaders
|
||||
Platform::MemoryClear(&Header, sizeof(Header));
|
||||
psDesc.InputLayout = { static_cast<D3D12_INPUT_ELEMENT_DESC*>(desc.VS->GetInputLayout()), desc.VS->GetInputLayoutSize() };
|
||||
#define INIT_SHADER_STAGE(stage, type) \
|
||||
if (desc.stage) \
|
||||
{ \
|
||||
@@ -172,14 +179,17 @@ bool GPUPipelineStateDX12::Init(const Description& desc)
|
||||
#endif
|
||||
INIT_SHADER_STAGE(VS, GPUShaderProgramVSDX12);
|
||||
INIT_SHADER_STAGE(PS, GPUShaderProgramPSDX12);
|
||||
const static D3D12_PRIMITIVE_TOPOLOGY_TYPE primTypes1[] =
|
||||
|
||||
// Input Assembly
|
||||
VertexLayout = desc.VS ? (GPUVertexLayoutDX12*)desc.VS->Layout : nullptr;
|
||||
const D3D12_PRIMITIVE_TOPOLOGY_TYPE primTypes1[] =
|
||||
{
|
||||
D3D12_PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED,
|
||||
D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT,
|
||||
D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE,
|
||||
D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,
|
||||
};
|
||||
const static D3D_PRIMITIVE_TOPOLOGY primTypes2[] =
|
||||
const D3D_PRIMITIVE_TOPOLOGY primTypes2[] =
|
||||
{
|
||||
D3D_PRIMITIVE_TOPOLOGY_UNDEFINED,
|
||||
D3D_PRIMITIVE_TOPOLOGY_POINTLIST,
|
||||
|
||||
@@ -11,11 +11,13 @@
|
||||
#include "../IncludeDirectXHeaders.h"
|
||||
|
||||
class GPUTextureViewDX12;
|
||||
class GPUVertexLayoutDX12;
|
||||
|
||||
struct GPUPipelineStateKeyDX12
|
||||
{
|
||||
int32 RTsCount;
|
||||
MSAALevel MSAA;
|
||||
GPUVertexLayout* VertexLayout;
|
||||
PixelFormat DepthFormat;
|
||||
PixelFormat RTVsFormats[GPU_MAX_RT_BINDED];
|
||||
|
||||
@@ -29,6 +31,7 @@ struct GPUPipelineStateKeyDX12
|
||||
uint32 hash = (int32)key.MSAA * 11;
|
||||
CombineHash(hash, (uint32)key.DepthFormat * 93473262);
|
||||
CombineHash(hash, key.RTsCount * 136);
|
||||
CombineHash(hash, GetHash(key.VertexLayout));
|
||||
CombineHash(hash, (uint32)key.RTVsFormats[0]);
|
||||
CombineHash(hash, (uint32)key.RTVsFormats[1]);
|
||||
CombineHash(hash, (uint32)key.RTVsFormats[2]);
|
||||
@@ -46,18 +49,16 @@ struct GPUPipelineStateKeyDX12
|
||||
class GPUPipelineStateDX12 : public GPUResourceDX12<GPUPipelineState>
|
||||
{
|
||||
private:
|
||||
|
||||
Dictionary<GPUPipelineStateKeyDX12, ID3D12PipelineState*> _states;
|
||||
D3D12_GRAPHICS_PIPELINE_STATE_DESC _desc;
|
||||
|
||||
public:
|
||||
|
||||
GPUPipelineStateDX12(GPUDeviceDX12* device);
|
||||
|
||||
public:
|
||||
|
||||
D3D_PRIMITIVE_TOPOLOGY PrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
|
||||
DxShaderHeader Header;
|
||||
GPUVertexLayoutDX12* VertexLayout;
|
||||
|
||||
/// <summary>
|
||||
/// Gets DirectX 12 graphics pipeline state object for the given rendering state. Uses depth buffer and render targets formats and multi-sample levels to setup a proper PSO. Uses caching.
|
||||
@@ -65,17 +66,16 @@ public:
|
||||
/// <param name="depth">The depth buffer (can be null).</param>
|
||||
/// <param name="rtCount">The render targets count (can be 0).</param>
|
||||
/// <param name="rtHandles">The render target handles array.</param>
|
||||
/// <param name="vertexLayout">The vertex buffers layout.</param>
|
||||
/// <returns>DirectX 12 graphics pipeline state object</returns>
|
||||
ID3D12PipelineState* GetState(GPUTextureViewDX12* depth, int32 rtCount, GPUTextureViewDX12** rtHandles);
|
||||
ID3D12PipelineState* GetState(GPUTextureViewDX12* depth, int32 rtCount, GPUTextureViewDX12** rtHandles, GPUVertexLayoutDX12* vertexLayout);
|
||||
|
||||
public:
|
||||
|
||||
// [GPUPipelineState]
|
||||
bool IsValid() const override;
|
||||
bool Init(const Description& desc) override;
|
||||
|
||||
protected:
|
||||
|
||||
// [GPUResourceDX12]
|
||||
void OnReleaseGPU() override;
|
||||
};
|
||||
|
||||
@@ -8,81 +8,19 @@
|
||||
#include "Types.h"
|
||||
#include "../RenderToolsDX.h"
|
||||
|
||||
GPUShaderProgram* GPUShaderDX12::CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, byte* cacheBytes, uint32 cacheSize, MemoryReadStream& stream)
|
||||
GPUShaderProgram* GPUShaderDX12::CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, Span<byte> bytecode, MemoryReadStream& stream)
|
||||
{
|
||||
// Extract the DX shader header from the cache
|
||||
DxShaderHeader* header = (DxShaderHeader*)cacheBytes;
|
||||
cacheBytes += sizeof(DxShaderHeader);
|
||||
cacheSize -= sizeof(DxShaderHeader);
|
||||
DxShaderHeader* header = (DxShaderHeader*)bytecode.Get();
|
||||
bytecode = Span<byte>(bytecode.Get() + sizeof(DxShaderHeader), bytecode.Length() - sizeof(DxShaderHeader));
|
||||
|
||||
GPUShaderProgram* shader = nullptr;
|
||||
switch (type)
|
||||
{
|
||||
case ShaderStage::Vertex:
|
||||
{
|
||||
// Load Input Layout (it may be empty)
|
||||
byte inputLayoutSize;
|
||||
stream.ReadByte(&inputLayoutSize);
|
||||
ASSERT(inputLayoutSize <= VERTEX_SHADER_MAX_INPUT_ELEMENTS);
|
||||
D3D12_INPUT_ELEMENT_DESC inputLayout[VERTEX_SHADER_MAX_INPUT_ELEMENTS];
|
||||
for (int32 a = 0; a < inputLayoutSize; a++)
|
||||
{
|
||||
// Read description
|
||||
GPUShaderProgramVS::InputElement inputElement;
|
||||
stream.Read(inputElement);
|
||||
|
||||
// Get semantic name
|
||||
const char* semanticName = nullptr;
|
||||
// TODO: maybe use enum+mapping ?
|
||||
switch (inputElement.Type)
|
||||
{
|
||||
case 1:
|
||||
semanticName = "POSITION";
|
||||
break;
|
||||
case 2:
|
||||
semanticName = "COLOR";
|
||||
break;
|
||||
case 3:
|
||||
semanticName = "TEXCOORD";
|
||||
break;
|
||||
case 4:
|
||||
semanticName = "NORMAL";
|
||||
break;
|
||||
case 5:
|
||||
semanticName = "TANGENT";
|
||||
break;
|
||||
case 6:
|
||||
semanticName = "BITANGENT";
|
||||
break;
|
||||
case 7:
|
||||
semanticName = "ATTRIBUTE";
|
||||
break;
|
||||
case 8:
|
||||
semanticName = "BLENDINDICES";
|
||||
break;
|
||||
case 9:
|
||||
semanticName = "BLENDWEIGHT";
|
||||
break;
|
||||
default:
|
||||
LOG(Fatal, "Invalid vertex shader element semantic type: {0}", inputElement.Type);
|
||||
break;
|
||||
}
|
||||
|
||||
// Set data
|
||||
inputLayout[a] =
|
||||
{
|
||||
semanticName,
|
||||
static_cast<UINT>(inputElement.Index),
|
||||
static_cast<DXGI_FORMAT>(inputElement.Format),
|
||||
static_cast<UINT>(inputElement.InputSlot),
|
||||
static_cast<UINT>(inputElement.AlignedByteOffset),
|
||||
static_cast<D3D12_INPUT_CLASSIFICATION>(inputElement.InputSlotClass),
|
||||
static_cast<UINT>(inputElement.InstanceDataStepRate)
|
||||
};
|
||||
}
|
||||
|
||||
// Create object
|
||||
shader = New<GPUShaderProgramVSDX12>(initializer, header, cacheBytes, cacheSize, inputLayout, inputLayoutSize);
|
||||
GPUVertexLayout* vertexLayout = ReadVertexLayout(stream);
|
||||
shader = New<GPUShaderProgramVSDX12>(initializer, header, bytecode, vertexLayout);
|
||||
break;
|
||||
}
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
@@ -90,12 +28,12 @@ GPUShaderProgram* GPUShaderDX12::CreateGPUShaderProgram(ShaderStage type, const
|
||||
{
|
||||
int32 controlPointsCount;
|
||||
stream.ReadInt32(&controlPointsCount);
|
||||
shader = New<GPUShaderProgramHSDX12>(initializer, header, cacheBytes, cacheSize, controlPointsCount);
|
||||
shader = New<GPUShaderProgramHSDX12>(initializer, header, bytecode, controlPointsCount);
|
||||
break;
|
||||
}
|
||||
case ShaderStage::Domain:
|
||||
{
|
||||
shader = New<GPUShaderProgramDSDX12>(initializer, header, cacheBytes, cacheSize);
|
||||
shader = New<GPUShaderProgramDSDX12>(initializer, header, bytecode);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
@@ -109,18 +47,18 @@ GPUShaderProgram* GPUShaderDX12::CreateGPUShaderProgram(ShaderStage type, const
|
||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||
case ShaderStage::Geometry:
|
||||
{
|
||||
shader = New<GPUShaderProgramGSDX12>(initializer, header, cacheBytes, cacheSize);
|
||||
shader = New<GPUShaderProgramGSDX12>(initializer, header, bytecode);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case ShaderStage::Pixel:
|
||||
{
|
||||
shader = New<GPUShaderProgramPSDX12>(initializer, header, cacheBytes, cacheSize);
|
||||
shader = New<GPUShaderProgramPSDX12>(initializer, header, bytecode);
|
||||
break;
|
||||
}
|
||||
case ShaderStage::Compute:
|
||||
{
|
||||
shader = New<GPUShaderProgramCSDX12>(_device, initializer, header, cacheBytes, cacheSize);
|
||||
shader = New<GPUShaderProgramCSDX12>(_device, initializer, header, bytecode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
|
||||
protected:
|
||||
// [GPUShader]
|
||||
GPUShaderProgram* CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, byte* cacheBytes, uint32 cacheSize, MemoryReadStream& stream) override;
|
||||
GPUShaderProgram* CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, Span<byte> bytecode, MemoryReadStream& stream) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#if GRAPHICS_API_DIRECTX12
|
||||
|
||||
#include "GPUDeviceDX12.h"
|
||||
#include "Engine/Core/Types/DataContainer.h"
|
||||
#include "Engine/Graphics/Shaders/GPUShaderProgram.h"
|
||||
#include "Types.h"
|
||||
#include "../IncludeDirectXHeaders.h"
|
||||
@@ -15,30 +16,27 @@
|
||||
template<typename BaseType>
|
||||
class GPUShaderProgramDX12 : public BaseType
|
||||
{
|
||||
protected:
|
||||
Array<byte> _data;
|
||||
|
||||
public:
|
||||
GPUShaderProgramDX12(const GPUShaderProgramInitializer& initializer, DxShaderHeader* header, byte* cacheBytes, uint32 cacheSize)
|
||||
GPUShaderProgramDX12(const GPUShaderProgramInitializer& initializer, const DxShaderHeader* header, Span<byte> bytecode)
|
||||
: Header(*header)
|
||||
{
|
||||
BaseType::Init(initializer);
|
||||
_data.Set(cacheBytes, cacheSize);
|
||||
Bytecode.Copy(bytecode);
|
||||
}
|
||||
|
||||
public:
|
||||
BytesContainer Bytecode;
|
||||
DxShaderHeader Header;
|
||||
|
||||
public:
|
||||
// [BaseType]
|
||||
void* GetBufferHandle() const override
|
||||
{
|
||||
return (void*)_data.Get();
|
||||
return (void*)Bytecode.Get();
|
||||
}
|
||||
|
||||
uint32 GetBufferSize() const override
|
||||
{
|
||||
return _data.Count();
|
||||
return Bytecode.Length();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -47,29 +45,11 @@ public:
|
||||
/// </summary>
|
||||
class GPUShaderProgramVSDX12 : public GPUShaderProgramDX12<GPUShaderProgramVS>
|
||||
{
|
||||
private:
|
||||
byte _inputLayoutSize;
|
||||
D3D12_INPUT_ELEMENT_DESC _inputLayout[VERTEX_SHADER_MAX_INPUT_ELEMENTS];
|
||||
|
||||
public:
|
||||
GPUShaderProgramVSDX12(const GPUShaderProgramInitializer& initializer, DxShaderHeader* header, byte* cacheBytes, uint32 cacheSize, D3D12_INPUT_ELEMENT_DESC* inputLayout, byte inputLayoutSize)
|
||||
: GPUShaderProgramDX12(initializer, header, cacheBytes, cacheSize)
|
||||
, _inputLayoutSize(inputLayoutSize)
|
||||
GPUShaderProgramVSDX12(const GPUShaderProgramInitializer& initializer, const DxShaderHeader* header, Span<byte> bytecode, GPUVertexLayout* vertexLayout)
|
||||
: GPUShaderProgramDX12(initializer, header, bytecode)
|
||||
{
|
||||
for (byte i = 0; i < inputLayoutSize; i++)
|
||||
_inputLayout[i] = inputLayout[i];
|
||||
}
|
||||
|
||||
public:
|
||||
// [GPUShaderProgramDX12]
|
||||
void* GetInputLayout() const override
|
||||
{
|
||||
return (void*)_inputLayout;
|
||||
}
|
||||
|
||||
byte GetInputLayoutSize() const override
|
||||
{
|
||||
return _inputLayoutSize;
|
||||
Layout = vertexLayout;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -80,8 +60,8 @@ public:
|
||||
class GPUShaderProgramHSDX12 : public GPUShaderProgramDX12<GPUShaderProgramHS>
|
||||
{
|
||||
public:
|
||||
GPUShaderProgramHSDX12(const GPUShaderProgramInitializer& initializer, DxShaderHeader* header, byte* cacheBytes, uint32 cacheSize, int32 controlPointsCount)
|
||||
: GPUShaderProgramDX12(initializer, header, cacheBytes, cacheSize)
|
||||
GPUShaderProgramHSDX12(const GPUShaderProgramInitializer& initializer, const DxShaderHeader* header, Span<byte> bytecode, int32 controlPointsCount)
|
||||
: GPUShaderProgramDX12(initializer, header, bytecode)
|
||||
{
|
||||
_controlPointsCount = controlPointsCount;
|
||||
}
|
||||
@@ -93,8 +73,8 @@ public:
|
||||
class GPUShaderProgramDSDX12 : public GPUShaderProgramDX12<GPUShaderProgramDS>
|
||||
{
|
||||
public:
|
||||
GPUShaderProgramDSDX12(const GPUShaderProgramInitializer& initializer, DxShaderHeader* header, byte* cacheBytes, uint32 cacheSize)
|
||||
: GPUShaderProgramDX12(initializer, header, cacheBytes, cacheSize)
|
||||
GPUShaderProgramDSDX12(const GPUShaderProgramInitializer& initializer, const DxShaderHeader* header, Span<byte> bytecode)
|
||||
: GPUShaderProgramDX12(initializer, header, bytecode)
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -107,8 +87,8 @@ public:
|
||||
class GPUShaderProgramGSDX12 : public GPUShaderProgramDX12<GPUShaderProgramGS>
|
||||
{
|
||||
public:
|
||||
GPUShaderProgramGSDX12(const GPUShaderProgramInitializer& initializer, DxShaderHeader* header, byte* cacheBytes, uint32 cacheSize)
|
||||
: GPUShaderProgramDX12(initializer, header, cacheBytes, cacheSize)
|
||||
GPUShaderProgramGSDX12(const GPUShaderProgramInitializer& initializer, const DxShaderHeader* header, Span<byte> bytecode)
|
||||
: GPUShaderProgramDX12(initializer, header, bytecode)
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -120,8 +100,8 @@ public:
|
||||
class GPUShaderProgramPSDX12 : public GPUShaderProgramDX12<GPUShaderProgramPS>
|
||||
{
|
||||
public:
|
||||
GPUShaderProgramPSDX12(const GPUShaderProgramInitializer& initializer, DxShaderHeader* header, byte* cacheBytes, uint32 cacheSize)
|
||||
: GPUShaderProgramDX12(initializer, header, cacheBytes, cacheSize)
|
||||
GPUShaderProgramPSDX12(const GPUShaderProgramInitializer& initializer, const DxShaderHeader* header, Span<byte> bytecode)
|
||||
: GPUShaderProgramDX12(initializer, header, bytecode)
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -137,8 +117,8 @@ private:
|
||||
ID3D12PipelineState* _state;
|
||||
|
||||
public:
|
||||
GPUShaderProgramCSDX12(GPUDeviceDX12* device, const GPUShaderProgramInitializer& initializer, DxShaderHeader* header, byte* cacheBytes, uint32 cacheSize)
|
||||
: GPUShaderProgramDX12(initializer, header, cacheBytes, cacheSize)
|
||||
GPUShaderProgramCSDX12(GPUDeviceDX12* device, const GPUShaderProgramInitializer& initializer, const DxShaderHeader* header, Span<byte> bytecode)
|
||||
: GPUShaderProgramDX12(initializer, header, bytecode)
|
||||
, _device(device)
|
||||
, _state(nullptr)
|
||||
{
|
||||
|
||||
@@ -17,8 +17,6 @@ struct DxShaderHeader
|
||||
/// The UAV dimensions per-slot.
|
||||
/// </summary>
|
||||
byte UaDimensions[4];
|
||||
|
||||
// .. rest is just a actual data array
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -116,7 +116,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
void BindVB(const Span<GPUBuffer*>& vertexBuffers, const uint32* vertexBuffersOffsets = nullptr) override
|
||||
void BindVB(const Span<GPUBuffer*>& vertexBuffers, const uint32* vertexBuffersOffsets = nullptr, GPUVertexLayout* vertexLayout = nullptr) override
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ class GPUShaderNull : public GPUShader
|
||||
protected:
|
||||
|
||||
// [GPUShader]
|
||||
GPUShaderProgram* CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, byte* cacheBytes, uint32 cacheSize, MemoryReadStream& stream) override
|
||||
GPUShaderProgram* CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, Span<byte> bytecode, MemoryReadStream& stream) override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "GPUBufferVulkan.h"
|
||||
#include "GPUShaderVulkan.h"
|
||||
#include "GPUSamplerVulkan.h"
|
||||
#include "GPUVertexLayoutVulkan.h"
|
||||
#include "GPUPipelineStateVulkan.h"
|
||||
#include "Engine/Profiler/RenderStats.h"
|
||||
#include "GPUShaderProgramVulkan.h"
|
||||
@@ -650,8 +651,14 @@ void GPUContextVulkan::OnDrawCall()
|
||||
}
|
||||
|
||||
// Bind any missing vertex buffers to null if required by the current state
|
||||
const auto vertexInputState = pipelineState->GetVertexInputState();
|
||||
const int32 missingVBs = vertexInputState->vertexBindingDescriptionCount - _vbCount;
|
||||
GPUVertexLayoutVulkan* vertexLayout = _vertexLayout ? _vertexLayout : pipelineState->VertexShaderLayout;
|
||||
#if GPU_ENABLE_ASSERTION_LOW_LAYERS
|
||||
if (!vertexLayout && pipelineState && !pipelineState->VertexShaderLayout && (pipelineState->UsedStagesMask & (1 << (int32)DescriptorSet::Vertex)) != 0 && !_vertexLayout && _vbCount)
|
||||
{
|
||||
LOG(Error, "Missing Vertex Layout (not assigned to GPUBuffer). Vertex Shader won't read valid data resulting incorrect visuals.");
|
||||
}
|
||||
#endif
|
||||
const int32 missingVBs = vertexLayout ? (int32)vertexLayout->CreateInfo.vertexBindingDescriptionCount - _vbCount : 0;
|
||||
if (missingVBs > 0)
|
||||
{
|
||||
VkBuffer buffers[GPU_MAX_VB_BINDED];
|
||||
@@ -676,7 +683,7 @@ void GPUContextVulkan::OnDrawCall()
|
||||
{
|
||||
_psDirtyFlag = false;
|
||||
const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer();
|
||||
const auto pipeline = pipelineState->GetState(_renderPass);
|
||||
const auto pipeline = pipelineState->GetState(_renderPass, _vertexLayout);
|
||||
vkCmdBindPipeline(cmdBuffer->GetHandle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||
RENDER_STAT_PS_STATE_CHANGE();
|
||||
}
|
||||
@@ -715,6 +722,7 @@ void GPUContextVulkan::FrameBegin()
|
||||
_stencilRef = 0;
|
||||
_renderPass = nullptr;
|
||||
_currentState = nullptr;
|
||||
_vertexLayout = nullptr;
|
||||
_rtDepth = nullptr;
|
||||
Platform::MemoryClear(_rtHandles, sizeof(_rtHandles));
|
||||
Platform::MemoryClear(_cbHandles, sizeof(_cbHandles));
|
||||
@@ -1023,9 +1031,10 @@ void GPUContextVulkan::BindUA(int32 slot, GPUResourceView* view)
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextVulkan::BindVB(const Span<GPUBuffer*>& vertexBuffers, const uint32* vertexBuffersOffsets)
|
||||
void GPUContextVulkan::BindVB(const Span<GPUBuffer*>& vertexBuffers, const uint32* vertexBuffersOffsets, GPUVertexLayout* vertexLayout)
|
||||
{
|
||||
_vbCount = vertexBuffers.Length();
|
||||
_vertexLayout = (GPUVertexLayoutVulkan*)(vertexLayout ? vertexLayout : GPUVertexLayout::Get(vertexBuffers));
|
||||
if (vertexBuffers.Length() == 0)
|
||||
return;
|
||||
const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer();
|
||||
|
||||
@@ -14,6 +14,7 @@ class CmdBufferManagerVulkan;
|
||||
class ResourceOwnerVulkan;
|
||||
class GPUTextureViewVulkan;
|
||||
class GPUBufferVulkan;
|
||||
class GPUVertexLayoutVulkan;
|
||||
class GPUPipelineStateVulkan;
|
||||
class ComputePipelineStateVulkan;
|
||||
class GPUConstantBufferVulkan;
|
||||
@@ -82,6 +83,7 @@ private:
|
||||
|
||||
RenderPassVulkan* _renderPass;
|
||||
GPUPipelineStateVulkan* _currentState;
|
||||
GPUVertexLayoutVulkan* _vertexLayout;
|
||||
GPUTextureViewVulkan* _rtDepth;
|
||||
GPUTextureViewVulkan* _rtHandles[GPU_MAX_RT_BINDED];
|
||||
DescriptorOwnerResourceVulkan* _cbHandles[GPU_MAX_CB_BINDED];
|
||||
@@ -168,7 +170,7 @@ public:
|
||||
void BindCB(int32 slot, GPUConstantBuffer* cb) override;
|
||||
void BindSR(int32 slot, GPUResourceView* view) override;
|
||||
void BindUA(int32 slot, GPUResourceView* view) override;
|
||||
void BindVB(const Span<GPUBuffer*>& vertexBuffers, const uint32* vertexBuffersOffsets = nullptr) override;
|
||||
void BindVB(const Span<GPUBuffer*>& vertexBuffers, const uint32* vertexBuffersOffsets = nullptr, GPUVertexLayout* vertexLayout = nullptr) override;
|
||||
void BindIB(GPUBuffer* indexBuffer) override;
|
||||
void BindSampler(int32 slot, GPUSampler* sampler) override;
|
||||
void UpdateCB(GPUConstantBuffer* cb, const void* data) override;
|
||||
|
||||
@@ -922,10 +922,10 @@ GPUTextureVulkan* HelperResourcesVulkan::GetDummyTexture(SpirvShaderResourceType
|
||||
|
||||
GPUBufferVulkan* HelperResourcesVulkan::GetDummyBuffer(PixelFormat format)
|
||||
{
|
||||
if (_dummyBuffers.IsEmpty())
|
||||
if (!_dummyBuffers)
|
||||
{
|
||||
_dummyBuffers.Resize((int32)PixelFormat::MAX);
|
||||
Platform::MemoryClear((void*)_dummyBuffers.Get(), (int32)PixelFormat::MAX * sizeof(void*));
|
||||
_dummyBuffers = (GPUBufferVulkan**)Allocator::Allocate((int32)PixelFormat::MAX * sizeof(void*));
|
||||
Platform::MemoryClear(_dummyBuffers, (int32)PixelFormat::MAX * sizeof(void*));
|
||||
}
|
||||
auto& dummyBuffer = _dummyBuffers[(int32)format];
|
||||
if (!dummyBuffer)
|
||||
@@ -941,7 +941,7 @@ GPUBufferVulkan* HelperResourcesVulkan::GetDummyVertexBuffer()
|
||||
if (!_dummyVB)
|
||||
{
|
||||
_dummyVB = (GPUBufferVulkan*)_device->CreateBuffer(TEXT("DummyVertexBuffer"));
|
||||
_dummyVB->Init(GPUBufferDescription::Vertex(sizeof(Color32), 1, &Color32::Transparent));
|
||||
_dummyVB->Init(GPUBufferDescription::Vertex(nullptr, sizeof(Color32), 1, &Color32::Transparent));
|
||||
}
|
||||
return _dummyVB;
|
||||
}
|
||||
@@ -950,9 +950,16 @@ void HelperResourcesVulkan::Dispose()
|
||||
{
|
||||
SAFE_DELETE_GPU_RESOURCES(_dummyTextures);
|
||||
SAFE_DELETE_GPU_RESOURCE(_dummyVB);
|
||||
for (GPUBuffer* buffer : _dummyBuffers)
|
||||
Delete(buffer);
|
||||
_dummyBuffers.Clear();
|
||||
if (_dummyBuffers)
|
||||
{
|
||||
for (int32 i = 0; i < (int32)PixelFormat::MAX; i++)
|
||||
{
|
||||
if (GPUBufferVulkan* buffer = _dummyBuffers[i])
|
||||
Delete(buffer);
|
||||
}
|
||||
Allocator::Free(_dummyBuffers);
|
||||
_dummyBuffers = nullptr;
|
||||
}
|
||||
|
||||
for (int32 i = 0; i < ARRAY_COUNT(_staticSamplers); i++)
|
||||
{
|
||||
|
||||
@@ -308,7 +308,7 @@ class HelperResourcesVulkan
|
||||
private:
|
||||
GPUDeviceVulkan* _device;
|
||||
GPUTextureVulkan* _dummyTextures[6];
|
||||
Array<GPUBufferVulkan*> _dummyBuffers;
|
||||
GPUBufferVulkan** _dummyBuffers = nullptr;
|
||||
GPUBufferVulkan* _dummyVB;
|
||||
VkSampler _staticSamplers[GPU_STATIC_SAMPLERS_COUNT];
|
||||
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
#if GRAPHICS_API_VULKAN
|
||||
|
||||
#include "GPUPipelineStateVulkan.h"
|
||||
#include "GPUVertexLayoutVulkan.h"
|
||||
#include "RenderToolsVulkan.h"
|
||||
#include "DescriptorSetVulkan.h"
|
||||
#include "GPUShaderProgramVulkan.h"
|
||||
#include "Engine/Core/Log.h"
|
||||
#include "Engine/Core/Types/Pair.h"
|
||||
#include "Engine/Profiler/ProfilerCPU.h"
|
||||
|
||||
static VkStencilOp ToVulkanStencilOp(const StencilOperation value)
|
||||
@@ -169,7 +171,6 @@ ComputePipelineStateVulkan::~ComputePipelineStateVulkan()
|
||||
|
||||
GPUPipelineStateVulkan::GPUPipelineStateVulkan(GPUDeviceVulkan* device)
|
||||
: GPUResourceVulkan<GPUPipelineState>(device, StringView::Empty)
|
||||
, _pipelines(16)
|
||||
, _layout(nullptr)
|
||||
{
|
||||
}
|
||||
@@ -201,25 +202,30 @@ PipelineLayoutVulkan* GPUPipelineStateVulkan::GetLayout()
|
||||
return _layout;
|
||||
}
|
||||
|
||||
VkPipeline GPUPipelineStateVulkan::GetState(RenderPassVulkan* renderPass)
|
||||
VkPipeline GPUPipelineStateVulkan::GetState(RenderPassVulkan* renderPass, GPUVertexLayoutVulkan* vertexLayout)
|
||||
{
|
||||
ASSERT(renderPass);
|
||||
if (!vertexLayout)
|
||||
vertexLayout = VertexShaderLayout;
|
||||
|
||||
// Try reuse cached version
|
||||
VkPipeline pipeline = VK_NULL_HANDLE;
|
||||
if (_pipelines.TryGet(renderPass, pipeline))
|
||||
const Pair<RenderPassVulkan*, GPUVertexLayoutVulkan*> key(renderPass, vertexLayout);
|
||||
if (_pipelines.TryGet(key, pipeline))
|
||||
{
|
||||
#if BUILD_DEBUG
|
||||
// Verify
|
||||
RenderPassVulkan* refKey = nullptr;
|
||||
Pair<RenderPassVulkan*, GPUVertexLayoutVulkan*> refKey(nullptr, nullptr);
|
||||
_pipelines.KeyOf(pipeline, &refKey);
|
||||
ASSERT(refKey == renderPass);
|
||||
ASSERT(refKey == key);
|
||||
#endif
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
PROFILE_CPU_NAMED("Create Pipeline");
|
||||
|
||||
// Bind vertex input
|
||||
_desc.pVertexInputState = vertexLayout ? &vertexLayout->CreateInfo : nullptr;
|
||||
|
||||
// Update description to match the pipeline
|
||||
_descColorBlend.attachmentCount = renderPass->Layout.RTsCount;
|
||||
_descMultisample.rasterizationSamples = (VkSampleCountFlagBits)renderPass->Layout.MSAA;
|
||||
@@ -245,7 +251,7 @@ VkPipeline GPUPipelineStateVulkan::GetState(RenderPassVulkan* renderPass)
|
||||
}
|
||||
|
||||
// Cache it
|
||||
_pipelines.Add(renderPass, pipeline);
|
||||
_pipelines.Add(key, pipeline);
|
||||
|
||||
return pipeline;
|
||||
}
|
||||
@@ -278,12 +284,9 @@ bool GPUPipelineStateVulkan::Init(const Description& desc)
|
||||
{
|
||||
ASSERT(!IsValid());
|
||||
|
||||
// Create description
|
||||
// Reset description
|
||||
RenderToolsVulkan::ZeroStruct(_desc, VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO);
|
||||
|
||||
// Vertex Input
|
||||
_desc.pVertexInputState = (VkPipelineVertexInputStateCreateInfo*)desc.VS->GetInputLayout();
|
||||
|
||||
// Stages
|
||||
UsedStagesMask = 0;
|
||||
HasDescriptorsPerStageMask = 0;
|
||||
@@ -318,6 +321,7 @@ bool GPUPipelineStateVulkan::Init(const Description& desc)
|
||||
_desc.pStages = _shaderStages;
|
||||
|
||||
// Input Assembly
|
||||
VertexShaderLayout = desc.VS ? (GPUVertexLayoutVulkan*)desc.VS->Layout : nullptr;
|
||||
RenderToolsVulkan::ZeroStruct(_descInputAssembly, VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO);;
|
||||
switch (desc.PrimitiveTopology)
|
||||
{
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#if GRAPHICS_API_VULKAN
|
||||
|
||||
class GPUVertexLayoutVulkan;
|
||||
class PipelineLayoutVulkan;
|
||||
|
||||
class ComputePipelineStateVulkan
|
||||
@@ -89,7 +90,7 @@ public:
|
||||
class GPUPipelineStateVulkan : public GPUResourceVulkan<GPUPipelineState>
|
||||
{
|
||||
private:
|
||||
Dictionary<RenderPassVulkan*, VkPipeline> _pipelines;
|
||||
Dictionary<Pair<RenderPassVulkan*, GPUVertexLayoutVulkan*>, VkPipeline> _pipelines;
|
||||
VkGraphicsPipelineCreateInfo _desc;
|
||||
VkPipelineShaderStageCreateInfo _shaderStages[ShaderStage_Count - 1];
|
||||
VkPipelineInputAssemblyStateCreateInfo _descInputAssembly;
|
||||
@@ -140,18 +141,13 @@ public:
|
||||
/// </summary>
|
||||
const SpirvShaderDescriptorInfo* DescriptorInfoPerStage[DescriptorSet::GraphicsStagesCount];
|
||||
|
||||
const VkPipelineVertexInputStateCreateInfo* GetVertexInputState() const
|
||||
{
|
||||
return _desc.pVertexInputState;
|
||||
}
|
||||
|
||||
DescriptorSetWriteContainerVulkan DSWriteContainer;
|
||||
DescriptorSetWriterVulkan DSWriter[DescriptorSet::GraphicsStagesCount];
|
||||
|
||||
const DescriptorSetLayoutVulkan* DescriptorSetsLayout = nullptr;
|
||||
TypedDescriptorPoolSetVulkan* CurrentTypedDescriptorPoolSet = nullptr;
|
||||
GPUVertexLayoutVulkan* VertexShaderLayout = nullptr;
|
||||
Array<VkDescriptorSet> DescriptorSetHandles;
|
||||
|
||||
Array<uint32> DynamicOffsets;
|
||||
|
||||
public:
|
||||
@@ -184,8 +180,9 @@ public:
|
||||
/// Gets the Vulkan graphics pipeline object for the given rendering state. Uses depth buffer and render targets formats and multi-sample levels to setup a proper PSO. Uses caching.
|
||||
/// </summary>
|
||||
/// <param name="renderPass">The render pass.</param>
|
||||
/// <param name="vertexLayout">The vertex layout.</param>
|
||||
/// <returns>Vulkan graphics pipeline object.</returns>
|
||||
VkPipeline GetState(RenderPassVulkan* renderPass);
|
||||
VkPipeline GetState(RenderPassVulkan* renderPass, GPUVertexLayoutVulkan* vertexLayout);
|
||||
|
||||
public:
|
||||
// [GPUPipelineState]
|
||||
|
||||
@@ -21,13 +21,6 @@ protected:
|
||||
GPUDeviceVulkan* _device;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUShaderProgramVulkan"/> class.
|
||||
/// </summary>
|
||||
/// <param name="device">The graphics device.</param>
|
||||
/// <param name="initializer">The program initialization data.</param>
|
||||
/// <param name="descriptorInfo">The program descriptors usage info.</param>
|
||||
/// <param name="shaderModule">The shader module object.</param>
|
||||
GPUShaderProgramVulkan(GPUDeviceVulkan* device, const GPUShaderProgramInitializer& initializer, const SpirvShaderDescriptorInfo& descriptorInfo, VkShaderModule shaderModule)
|
||||
: _device(device)
|
||||
, ShaderModule(shaderModule)
|
||||
@@ -36,9 +29,6 @@ public:
|
||||
BaseType::Init(initializer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes an instance of the <see cref="GPUShaderProgramVulkan"/> class.
|
||||
/// </summary>
|
||||
~GPUShaderProgramVulkan()
|
||||
{
|
||||
if (ShaderModule)
|
||||
@@ -64,7 +54,6 @@ public:
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* GetBufferHandle() const override
|
||||
{
|
||||
return (void*)ShaderModule;
|
||||
@@ -77,33 +66,10 @@ public:
|
||||
class GPUShaderProgramVSVulkan : public GPUShaderProgramVulkan<GPUShaderProgramVS>
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUShaderProgramVSVulkan"/> class.
|
||||
/// </summary>
|
||||
/// <param name="device">The graphics device.</param>
|
||||
/// <param name="initializer">The program initialization data.</param>
|
||||
/// <param name="descriptorInfo">The program descriptors usage info.</param>
|
||||
/// <param name="shaderModule">The shader module object.</param>
|
||||
GPUShaderProgramVSVulkan(GPUDeviceVulkan* device, const GPUShaderProgramInitializer& initializer, const SpirvShaderDescriptorInfo& descriptorInfo, VkShaderModule shaderModule)
|
||||
GPUShaderProgramVSVulkan(GPUDeviceVulkan* device, const GPUShaderProgramInitializer& initializer, const SpirvShaderDescriptorInfo& descriptorInfo, VkShaderModule shaderModule, GPUVertexLayout* vertexLayout)
|
||||
: GPUShaderProgramVulkan(device, initializer, descriptorInfo, shaderModule)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
VkPipelineVertexInputStateCreateInfo VertexInputState;
|
||||
VkVertexInputBindingDescription VertexBindingDescriptions[VERTEX_SHADER_MAX_INPUT_ELEMENTS];
|
||||
VkVertexInputAttributeDescription VertexAttributeDescriptions[VERTEX_SHADER_MAX_INPUT_ELEMENTS];
|
||||
|
||||
public:
|
||||
// [GPUShaderProgramVulkan]
|
||||
void* GetInputLayout() const override
|
||||
{
|
||||
return (void*)&VertexInputState;
|
||||
}
|
||||
|
||||
byte GetInputLayoutSize() const override
|
||||
{
|
||||
return 0;
|
||||
Layout = vertexLayout;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -114,14 +80,6 @@ public:
|
||||
class GPUShaderProgramHSVulkan : public GPUShaderProgramVulkan<GPUShaderProgramHS>
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUShaderProgramHSVulkan"/> class.
|
||||
/// </summary>
|
||||
/// <param name="device">The graphics device.</param>
|
||||
/// <param name="initializer">The program initialization data.</param>
|
||||
/// <param name="descriptorInfo">The program descriptors usage info.</param>
|
||||
/// <param name="shaderModule">The shader module object.</param>
|
||||
/// <param name="controlPointsCount">The control points used by the hull shader for processing.</param>
|
||||
GPUShaderProgramHSVulkan(GPUDeviceVulkan* device, const GPUShaderProgramInitializer& initializer, const SpirvShaderDescriptorInfo& descriptorInfo, VkShaderModule shaderModule, int32 controlPointsCount)
|
||||
: GPUShaderProgramVulkan(device, initializer, descriptorInfo, shaderModule)
|
||||
{
|
||||
@@ -135,13 +93,6 @@ public:
|
||||
class GPUShaderProgramDSVulkan : public GPUShaderProgramVulkan<GPUShaderProgramDS>
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUShaderProgramDSVulkan"/> class.
|
||||
/// </summary>
|
||||
/// <param name="device">The graphics device.</param>
|
||||
/// <param name="initializer">The program initialization data.</param>
|
||||
/// <param name="descriptorInfo">The program descriptors usage info.</param>
|
||||
/// <param name="shaderModule">The shader module object.</param>
|
||||
GPUShaderProgramDSVulkan(GPUDeviceVulkan* device, const GPUShaderProgramInitializer& initializer, const SpirvShaderDescriptorInfo& descriptorInfo, VkShaderModule shaderModule)
|
||||
: GPUShaderProgramVulkan(device, initializer, descriptorInfo, shaderModule)
|
||||
{
|
||||
@@ -156,13 +107,6 @@ public:
|
||||
class GPUShaderProgramGSVulkan : public GPUShaderProgramVulkan<GPUShaderProgramGS>
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUShaderProgramGSVulkan"/> class.
|
||||
/// </summary>
|
||||
/// <param name="device">The graphics device.</param>
|
||||
/// <param name="initializer">The program initialization data.</param>
|
||||
/// <param name="descriptorInfo">The program descriptors usage info.</param>
|
||||
/// <param name="shaderModule">The shader module object.</param>
|
||||
GPUShaderProgramGSVulkan(GPUDeviceVulkan* device, const GPUShaderProgramInitializer& initializer, const SpirvShaderDescriptorInfo& descriptorInfo, VkShaderModule shaderModule)
|
||||
: GPUShaderProgramVulkan(device, initializer, descriptorInfo, shaderModule)
|
||||
{
|
||||
@@ -176,13 +120,6 @@ public:
|
||||
class GPUShaderProgramPSVulkan : public GPUShaderProgramVulkan<GPUShaderProgramPS>
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUShaderProgramPSVulkan"/> class.
|
||||
/// </summary>
|
||||
/// <param name="device">The graphics device.</param>
|
||||
/// <param name="initializer">The program initialization data.</param>
|
||||
/// <param name="descriptorInfo">The program descriptors usage info.</param>
|
||||
/// <param name="shaderModule">The shader module object.</param>
|
||||
GPUShaderProgramPSVulkan(GPUDeviceVulkan* device, const GPUShaderProgramInitializer& initializer, const SpirvShaderDescriptorInfo& descriptorInfo, VkShaderModule shaderModule)
|
||||
: GPUShaderProgramVulkan(device, initializer, descriptorInfo, shaderModule)
|
||||
{
|
||||
@@ -198,29 +135,18 @@ private:
|
||||
ComputePipelineStateVulkan* _pipelineState;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUShaderProgramCSVulkan"/> class.
|
||||
/// </summary>
|
||||
/// <param name="device">The graphics device.</param>
|
||||
/// <param name="initializer">The program initialization data.</param>
|
||||
/// <param name="descriptorInfo">The program descriptors usage info.</param>
|
||||
/// <param name="shaderModule">The shader module object.</param>
|
||||
GPUShaderProgramCSVulkan(GPUDeviceVulkan* device, const GPUShaderProgramInitializer& initializer, const SpirvShaderDescriptorInfo& descriptorInfo, VkShaderModule shaderModule)
|
||||
: GPUShaderProgramVulkan(device, initializer, descriptorInfo, shaderModule)
|
||||
, _pipelineState(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes an instance of the <see cref="GPUShaderProgramCSVulkan"/> class.
|
||||
/// </summary>
|
||||
~GPUShaderProgramCSVulkan();
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Gets the state of the pipeline for the compute shader execution or creates a new one if missing.
|
||||
/// </summary>
|
||||
/// <returns>The compute pipeline state.</returns>
|
||||
ComputePipelineStateVulkan* GetOrCreateState();
|
||||
};
|
||||
|
||||
|
||||
@@ -98,17 +98,16 @@ void UniformBufferUploaderVulkan::OnReleaseGPU()
|
||||
}
|
||||
}
|
||||
|
||||
GPUShaderProgram* GPUShaderVulkan::CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, byte* cacheBytes, uint32 cacheSize, MemoryReadStream& stream)
|
||||
GPUShaderProgram* GPUShaderVulkan::CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, Span<byte> bytecode, MemoryReadStream& stream)
|
||||
{
|
||||
// Extract the SPIR-V shader header from the cache
|
||||
SpirvShaderHeader* header = (SpirvShaderHeader*)cacheBytes;
|
||||
cacheBytes += sizeof(SpirvShaderHeader);
|
||||
cacheSize -= sizeof(SpirvShaderHeader);
|
||||
SpirvShaderHeader* header = (SpirvShaderHeader*)bytecode.Get();
|
||||
bytecode = Span<byte>(bytecode.Get() + sizeof(SpirvShaderHeader), bytecode.Length() - sizeof(SpirvShaderHeader));
|
||||
|
||||
// Extract the SPIR-V bytecode
|
||||
BytesContainer spirv;
|
||||
ASSERT(header->Type == SpirvShaderHeader::Types::Raw);
|
||||
spirv.Link(cacheBytes, cacheSize);
|
||||
spirv.Link(bytecode);
|
||||
|
||||
// Create shader module from SPIR-V bytecode
|
||||
VkShaderModule shaderModule = VK_NULL_HANDLE;
|
||||
@@ -139,59 +138,8 @@ GPUShaderProgram* GPUShaderVulkan::CreateGPUShaderProgram(ShaderStage type, cons
|
||||
{
|
||||
case ShaderStage::Vertex:
|
||||
{
|
||||
// Create object
|
||||
auto vsShader = New<GPUShaderProgramVSVulkan>(_device, initializer, header->DescriptorInfo, shaderModule);
|
||||
shader = vsShader;
|
||||
VkPipelineVertexInputStateCreateInfo& inputState = vsShader->VertexInputState;
|
||||
VkVertexInputBindingDescription* vertexBindingDescriptions = vsShader->VertexBindingDescriptions;
|
||||
VkVertexInputAttributeDescription* vertexAttributeDescriptions = vsShader->VertexAttributeDescriptions;
|
||||
RenderToolsVulkan::ZeroStruct(inputState, VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO);
|
||||
for (int32 i = 0; i < VERTEX_SHADER_MAX_INPUT_ELEMENTS; i++)
|
||||
{
|
||||
vertexBindingDescriptions[i].binding = i;
|
||||
vertexBindingDescriptions[i].stride = 0;
|
||||
vertexBindingDescriptions[i].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||
}
|
||||
|
||||
// Load Input Layout (it may be empty)
|
||||
byte inputLayoutSize;
|
||||
stream.ReadByte(&inputLayoutSize);
|
||||
ASSERT(inputLayoutSize <= VERTEX_SHADER_MAX_INPUT_ELEMENTS);
|
||||
uint32 attributesCount = inputLayoutSize;
|
||||
uint32 bindingsCount = 0;
|
||||
int32 offset = 0;
|
||||
for (int32 a = 0; a < inputLayoutSize; a++)
|
||||
{
|
||||
// Read description
|
||||
GPUShaderProgramVS::InputElement inputElement;
|
||||
stream.Read(inputElement);
|
||||
|
||||
const auto size = PixelFormatExtensions::SizeInBytes((PixelFormat)inputElement.Format);
|
||||
if (inputElement.AlignedByteOffset != INPUT_LAYOUT_ELEMENT_ALIGN)
|
||||
offset = inputElement.AlignedByteOffset;
|
||||
|
||||
auto& vertexBindingDescription = vertexBindingDescriptions[inputElement.InputSlot];
|
||||
vertexBindingDescription.binding = inputElement.InputSlot;
|
||||
vertexBindingDescription.stride = Math::Max(vertexBindingDescription.stride, (uint32_t)(offset + size));
|
||||
vertexBindingDescription.inputRate = inputElement.InputSlotClass == INPUT_LAYOUT_ELEMENT_PER_VERTEX_DATA ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE;
|
||||
ASSERT(inputElement.InstanceDataStepRate == 0 || inputElement.InstanceDataStepRate == 1);
|
||||
|
||||
auto& vertexAttributeDescription = vertexAttributeDescriptions[a];
|
||||
vertexAttributeDescription.location = a;
|
||||
vertexAttributeDescription.binding = inputElement.InputSlot;
|
||||
vertexAttributeDescription.format = RenderToolsVulkan::ToVulkanFormat((PixelFormat)inputElement.Format);
|
||||
vertexAttributeDescription.offset = offset;
|
||||
|
||||
bindingsCount = Math::Max(bindingsCount, (uint32)inputElement.InputSlot + 1);
|
||||
offset += size;
|
||||
}
|
||||
|
||||
inputState.vertexBindingDescriptionCount = bindingsCount;
|
||||
inputState.pVertexBindingDescriptions = vertexBindingDescriptions;
|
||||
|
||||
inputState.vertexAttributeDescriptionCount = attributesCount;
|
||||
inputState.pVertexAttributeDescriptions = vertexAttributeDescriptions;
|
||||
|
||||
GPUVertexLayout* vertexLayout = ReadVertexLayout(stream);
|
||||
shader = New<GPUShaderProgramVSVulkan>(_device, initializer, header->DescriptorInfo, shaderModule, vertexLayout);
|
||||
break;
|
||||
}
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
|
||||
@@ -130,7 +130,7 @@ public:
|
||||
|
||||
protected:
|
||||
// [GPUShader]
|
||||
GPUShaderProgram* CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, byte* cacheBytes, uint32 cacheSize, MemoryReadStream& stream) override;
|
||||
GPUShaderProgram* CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, Span<byte> bytecode, MemoryReadStream& stream) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -300,7 +300,7 @@ void StaticModel::FlushVertexColors()
|
||||
vertexColorsBuffer = GPUDevice::Instance->CreateBuffer(TEXT("VertexColors"));
|
||||
if (vertexColorsBuffer->GetSize() != size)
|
||||
{
|
||||
if (vertexColorsBuffer->Init(GPUBufferDescription::Vertex(sizeof(Color32), vertexColorsData.Count())))
|
||||
if (vertexColorsBuffer->Init(GPUBufferDescription::Vertex(VB2ElementType::GetLayout(), sizeof(Color32), vertexColorsData.Count(), nullptr)))
|
||||
break;
|
||||
}
|
||||
GPUDevice::Instance->GetMainContext()->UpdateBuffer(vertexColorsBuffer, vertexColorsData.Get(), size);
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "Engine/Graphics/DynamicBuffer.h"
|
||||
#include "Engine/Graphics/GPUContext.h"
|
||||
#include "Engine/Graphics/RenderTools.h"
|
||||
#include "Engine/Graphics/Shaders/GPUVertexLayout.h"
|
||||
#include "Engine/Profiler/ProfilerCPU.h"
|
||||
#include "Engine/Renderer/DrawCall.h"
|
||||
#include "Engine/Renderer/RenderList.h"
|
||||
@@ -49,17 +50,22 @@ public:
|
||||
{
|
||||
if (VB)
|
||||
return false;
|
||||
VB = GPUDevice::Instance->CreateBuffer(TEXT("SpriteParticleRenderer,VB"));
|
||||
VB = GPUDevice::Instance->CreateBuffer(TEXT("SpriteParticleRenderer.VB"));
|
||||
IB = GPUDevice::Instance->CreateBuffer(TEXT("SpriteParticleRenderer.IB"));
|
||||
static SpriteParticleVertex vertexBuffer[] =
|
||||
SpriteParticleVertex vertexBuffer[] =
|
||||
{
|
||||
{ -0.5f, -0.5f, 0.0f, 0.0f },
|
||||
{ +0.5f, -0.5f, 1.0f, 0.0f },
|
||||
{ +0.5f, +0.5f, 1.0f, 1.0f },
|
||||
{ -0.5f, +0.5f, 0.0f, 1.0f },
|
||||
};
|
||||
static uint16 indexBuffer[] = { 0, 1, 2, 0, 2, 3, };
|
||||
return VB->Init(GPUBufferDescription::Vertex(sizeof(SpriteParticleVertex), VertexCount, vertexBuffer)) || IB->Init(GPUBufferDescription::Index(sizeof(uint16), IndexCount, indexBuffer));
|
||||
uint16 indexBuffer[] = { 0, 1, 2, 0, 2, 3, };
|
||||
auto layout = GPUVertexLayout::Get({
|
||||
{ VertexElement::Types::Position, 0, 0, 0, PixelFormat::R32G32_Float },
|
||||
{ VertexElement::Types::TexCoord, 0, 0, 0, PixelFormat::R32G32_Float },
|
||||
});
|
||||
return VB->Init(GPUBufferDescription::Vertex(layout, sizeof(SpriteParticleVertex), VertexCount, vertexBuffer)) ||
|
||||
IB->Init(GPUBufferDescription::Index(sizeof(uint16), IndexCount, indexBuffer));
|
||||
}
|
||||
|
||||
void Dispose()
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "Engine/Graphics/DynamicBuffer.h"
|
||||
#include "Engine/Graphics/Shaders/GPUShader.h"
|
||||
#include "Engine/Graphics/Shaders/GPUConstantBuffer.h"
|
||||
#include "Engine/Graphics/Shaders/GPUVertexLayout.h"
|
||||
#include "Engine/Animations/AnimationUtils.h"
|
||||
#include "Engine/Core/Log.h"
|
||||
#include "Engine/Core/Math/Half.h"
|
||||
@@ -604,6 +605,14 @@ bool Render2DService::Init()
|
||||
GUIShader.Get()->OnReloading.Bind<OnGUIShaderReloading>();
|
||||
#endif
|
||||
|
||||
VB.SetLayout(GPUVertexLayout::Get({
|
||||
{ VertexElement::Types::Position, 0, 0, 0, PixelFormat::R32G32_Float },
|
||||
{ VertexElement::Types::TexCoord, 0, 0, 0, PixelFormat::R16G16_Float },
|
||||
{ VertexElement::Types::Color, 0, 0, 0, PixelFormat::R32G32B32A32_Float },
|
||||
{ VertexElement::Types::TexCoord1, 0, 0, 0, PixelFormat::R32G32B32A32_Float },
|
||||
{ VertexElement::Types::TexCoord2, 0, 0, 0, PixelFormat::R32G32B32A32_Float },
|
||||
}));
|
||||
|
||||
DrawCalls.EnsureCapacity(RENDER2D_INITIAL_DRAW_CALL_CAPACITY);
|
||||
|
||||
return false;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "Engine/Graphics/RenderTargetPool.h"
|
||||
#include "Engine/Graphics/Async/GPUSyncPoint.h"
|
||||
#include "Engine/Graphics/Shaders/GPUShader.h"
|
||||
#include "Engine/Graphics/Shaders/GPUVertexLayout.h"
|
||||
#include "Engine/Level/Actors/StaticModel.h"
|
||||
#include "Engine/Level/Scene/SceneRendering.h"
|
||||
#include "Engine/Renderer/ColorGradingPass.h"
|
||||
@@ -767,7 +768,14 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
|
||||
for (SceneRendering* scene : renderContext.List->Scenes)
|
||||
surfaceAtlasData.ListenSceneRendering(scene);
|
||||
if (!_vertexBuffer)
|
||||
_vertexBuffer = New<DynamicVertexBuffer>(0u, (uint32)sizeof(AtlasTileVertex), TEXT("GlobalSurfaceAtlas.VertexBuffer"));
|
||||
{
|
||||
auto layout = GPUVertexLayout::Get({
|
||||
{ VertexElement::Types::Position, 0, 0, 0, PixelFormat::R16G16_Float },
|
||||
{ VertexElement::Types::TexCoord0, 0, 0, 0, PixelFormat::R16G16_Float },
|
||||
{ VertexElement::Types::TexCoord1, 0, 0, 0, PixelFormat::R32_UInt },
|
||||
});
|
||||
_vertexBuffer = New<DynamicVertexBuffer>(0u, (uint32)sizeof(AtlasTileVertex), TEXT("GlobalSurfaceAtlas.VertexBuffer"), layout);
|
||||
}
|
||||
|
||||
// Ensure that async objects drawing ended
|
||||
_surfaceAtlasData = &surfaceAtlasData;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "Engine/Profiler/Profiler.h"
|
||||
#include "Engine/Content/Assets/CubeTexture.h"
|
||||
#include "Engine/Core/Log.h"
|
||||
#include "Engine/Graphics/Shaders/GPUVertexLayout.h"
|
||||
#include "Engine/Level/Scene/Lightmap.h"
|
||||
#include "Engine/Level/Actors/PostFxVolume.h"
|
||||
|
||||
@@ -444,7 +445,7 @@ RenderList::RenderList(const SpawnParams& params)
|
||||
, Blendable(32)
|
||||
, ObjectBuffer(0, PixelFormat::R32G32B32A32_Float, false, TEXT("Object Bufffer"))
|
||||
, TempObjectBuffer(0, PixelFormat::R32G32B32A32_Float, false, TEXT("Object Bufffer"))
|
||||
, _instanceBuffer(0, sizeof(ShaderObjectDrawInstanceData), TEXT("Instance Buffer"))
|
||||
, _instanceBuffer(0, sizeof(ShaderObjectDrawInstanceData), TEXT("Instance Buffer"), GPUVertexLayout::Get({ { VertexElement::Types::Attribute0, 3, 0, 1, PixelFormat::R32_UInt } }))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "Engine/Graphics/RenderTargetPool.h"
|
||||
#include "Engine/Graphics/GPULimits.h"
|
||||
#include "Engine/Graphics/GPUContext.h"
|
||||
#include "Engine/Graphics/Shaders/GPUVertexLayout.h"
|
||||
#include "Engine/Content/Assets/CubeTexture.h"
|
||||
#include "Engine/Content/Content.h"
|
||||
#include "Engine/Engine/Engine.h"
|
||||
@@ -627,10 +628,11 @@ void VolumetricFogPass::InitCircleBuffer()
|
||||
}
|
||||
|
||||
// Create buffers
|
||||
ASSERT(_vbCircleRasterize == nullptr && _ibCircleRasterize == nullptr);
|
||||
ASSERT_LOW_LAYER(_vbCircleRasterize == nullptr && _ibCircleRasterize == nullptr);
|
||||
_vbCircleRasterize = GPUDevice::Instance->CreateBuffer(TEXT("VolumetricFog.CircleRasterize.VB"));
|
||||
_ibCircleRasterize = GPUDevice::Instance->CreateBuffer(TEXT("VolumetricFog.CircleRasterize.IB"));
|
||||
if (_vbCircleRasterize->Init(GPUBufferDescription::Vertex(sizeof(Float2), vertices, vbData))
|
||||
auto layout = GPUVertexLayout::Get({{ VertexElement::Types::TexCoord, 0, 0, 0, PixelFormat::R32G32_Float }});
|
||||
if (_vbCircleRasterize->Init(GPUBufferDescription::Vertex(layout, sizeof(Float2), vertices, vbData))
|
||||
|| _ibCircleRasterize->Init(GPUBufferDescription::Index(sizeof(uint16), triangles * 3, ibData)))
|
||||
{
|
||||
LOG(Fatal, "Failed to setup volumetric fog buffers.");
|
||||
|
||||
@@ -84,6 +84,11 @@ namespace ShaderProcessing
|
||||
parser->OnError(TEXT("Cannot parse token."));
|
||||
return;
|
||||
}
|
||||
else if (element.AlignedByteOffset > MAX_uint8)
|
||||
{
|
||||
parser->OnError(TEXT("Too big vertex element byte offset."));
|
||||
return;
|
||||
}
|
||||
|
||||
// Input slot class
|
||||
text.ReadToken(&token);
|
||||
@@ -140,9 +145,9 @@ namespace ShaderProcessing
|
||||
void OnParseAfter(IShaderParser* parser, Reader& text) override
|
||||
{
|
||||
// Check if errors in specified input layout
|
||||
if (_current.InputLayout.Count() > VERTEX_SHADER_MAX_INPUT_ELEMENTS)
|
||||
if (_current.InputLayout.Count() > GPU_MAX_VS_ELEMENTS)
|
||||
{
|
||||
parser->OnError(String::Format(TEXT("Vertex Shader \'{0}\' has too many input layout elements specified. Maximum allowed amount is {1}."), String(_current.Name), VERTEX_SHADER_MAX_INPUT_ELEMENTS));
|
||||
parser->OnError(String::Format(TEXT("Vertex Shader \'{0}\' has too many input layout elements specified. Maximum allowed amount is {1}."), String(_current.Name), GPU_MAX_VS_ELEMENTS));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,9 +10,11 @@
|
||||
#include "Engine/Platform/FileSystem.h"
|
||||
#include "Engine/Graphics/RenderTools.h"
|
||||
#include "Engine/Graphics/Shaders/GPUShader.h"
|
||||
#include "Engine/Graphics/Shaders/VertexElement.h"
|
||||
#include "Engine/Threading/Threading.h"
|
||||
#include "Engine/Profiler/ProfilerCPU.h"
|
||||
#include "Engine/Serialization/MemoryWriteStream.h"
|
||||
#include "FlaxEngine.Gen.h"
|
||||
|
||||
namespace IncludedFiles
|
||||
{
|
||||
@@ -65,14 +67,11 @@ bool ShaderCompiler::Compile(ShaderCompilationContext* context)
|
||||
return true;
|
||||
|
||||
// [Output] Constant Buffers
|
||||
output->WriteByte((byte)_constantBuffers.Count());
|
||||
for (const ShaderResourceBuffer& cb : _constantBuffers)
|
||||
{
|
||||
ASSERT(_constantBuffers.Count() == meta->CB.Count());
|
||||
output->WriteByte((byte)_constantBuffers.Count());
|
||||
for (const ShaderResourceBuffer& cb : _constantBuffers)
|
||||
{
|
||||
output->WriteByte(cb.Slot);
|
||||
output->WriteUint32(cb.Size);
|
||||
}
|
||||
output->WriteByte(cb.Slot);
|
||||
output->WriteUint32(cb.Size);
|
||||
}
|
||||
|
||||
// Additional Data Start
|
||||
@@ -314,13 +313,21 @@ bool ShaderCompiler::WriteShaderFunctionEnd(ShaderCompilationContext* context, S
|
||||
|
||||
bool ShaderCompiler::WriteCustomDataVS(ShaderCompilationContext* context, ShaderFunctionMeta& meta, int32 permutationIndex, const Array<ShaderMacro>& macros)
|
||||
{
|
||||
// [Deprecated in v1.10]
|
||||
auto output = context->Output;
|
||||
auto& metaVS = *(VertexShaderMeta*)&meta;
|
||||
auto& layout = metaVS.InputLayout;
|
||||
#if FLAXENGINE_VERSION_MAJOR > 2 || (FLAXENGINE_VERSION_MAJOR == 2 && FLAXENGINE_VERSION_MINOR >= 1)
|
||||
if (layout.HasItems())
|
||||
LOG(Warning, "Vertex Shader '{}' (asset '{}') uses explicit vertex layout via 'META_VS_IN_ELEMENT' macros which has been deprecated. Remove this code and migrate to GPUVertexLayout with VertexElement array in code (assigned to vertex buffer).", String(meta.Name), context->Options->TargetName);
|
||||
#elif FLAXENGINE_VERSION_MAJOR == 1 && FLAXENGINE_VERSION_MINOR >= 11
|
||||
if (layout.HasItems())
|
||||
LOG(Warning, "Vertex Shader '{}' (asset '{}') uses explicit vertex layout via 'META_VS_IN_ELEMENT' macros which has been deprecated. Remove this code and migrate to GPUVertexLayout with VertexElement array in code (assigned to vertex buffer).", String(meta.Name), context->Options->TargetName);
|
||||
#endif
|
||||
|
||||
// Get visible entries (based on `visible` flag switch)
|
||||
int32 layoutSize = 0;
|
||||
bool layoutVisible[VERTEX_SHADER_MAX_INPUT_ELEMENTS];
|
||||
bool layoutVisible[GPU_MAX_VS_ELEMENTS];
|
||||
for (int32 i = 0; i < layout.Count(); i++)
|
||||
{
|
||||
auto& element = layout[i];
|
||||
@@ -361,14 +368,93 @@ bool ShaderCompiler::WriteCustomDataVS(ShaderCompilationContext* context, Shader
|
||||
auto& element = layout[a];
|
||||
if (!layoutVisible[a])
|
||||
continue;
|
||||
GPUShaderProgramVS::InputElement data;
|
||||
data.Type = static_cast<byte>(element.Type);
|
||||
data.Index = element.Index;
|
||||
data.Format = static_cast<byte>(element.Format);
|
||||
data.InputSlot = element.InputSlot;
|
||||
data.AlignedByteOffset = element.AlignedByteOffset;
|
||||
data.InputSlotClass = element.InputSlotClass;
|
||||
data.InstanceDataStepRate = element.InstanceDataStepRate;
|
||||
VertexElement data;
|
||||
switch (element.Type)
|
||||
{
|
||||
case VertexShaderMeta::InputType::POSITION:
|
||||
data.Type = VertexElement::Types::Position;
|
||||
break;
|
||||
case VertexShaderMeta::InputType::COLOR:
|
||||
data.Type = VertexElement::Types::Color;
|
||||
break;
|
||||
case VertexShaderMeta::InputType::TEXCOORD:
|
||||
switch (element.Index)
|
||||
{
|
||||
case 0:
|
||||
data.Type = VertexElement::Types::TexCoord0;
|
||||
break;
|
||||
case 1:
|
||||
data.Type = VertexElement::Types::TexCoord1;
|
||||
break;
|
||||
case 2:
|
||||
data.Type = VertexElement::Types::TexCoord2;
|
||||
break;
|
||||
case 3:
|
||||
data.Type = VertexElement::Types::TexCoord3;
|
||||
break;
|
||||
case 4:
|
||||
data.Type = VertexElement::Types::TexCoord4;
|
||||
break;
|
||||
case 5:
|
||||
data.Type = VertexElement::Types::TexCoord5;
|
||||
break;
|
||||
case 6:
|
||||
data.Type = VertexElement::Types::TexCoord6;
|
||||
break;
|
||||
case 7:
|
||||
data.Type = VertexElement::Types::TexCoord7;
|
||||
break;
|
||||
default:
|
||||
LOG(Error, "Vertex Shader '{}' (asset '{}') uses deprecated texcoord attribute index. Valid range is 0-7.", String(meta.Name), context->Options->TargetName);
|
||||
data.Type = VertexElement::Types::TexCoord;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case VertexShaderMeta::InputType::NORMAL:
|
||||
data.Type = VertexElement::Types::Normal;
|
||||
break;
|
||||
case VertexShaderMeta::InputType::TANGENT:
|
||||
data.Type = VertexElement::Types::Tangent;
|
||||
break;
|
||||
case VertexShaderMeta::InputType::BITANGENT:
|
||||
LOG(Error, "Vertex Shader '{}' (asset '{}') uses deprecated attribute 'BITANGENT'. Remapping it to `ATTRIBUTE`.", String(meta.Name), context->Options->TargetName);
|
||||
data.Type = VertexElement::Types::Attribute;
|
||||
break;
|
||||
case VertexShaderMeta::InputType::ATTRIBUTE:
|
||||
switch (element.Index)
|
||||
{
|
||||
case 0:
|
||||
data.Type = VertexElement::Types::Attribute0;
|
||||
break;
|
||||
case 1:
|
||||
data.Type = VertexElement::Types::Attribute1;
|
||||
break;
|
||||
case 2:
|
||||
data.Type = VertexElement::Types::Attribute2;
|
||||
break;
|
||||
case 3:
|
||||
data.Type = VertexElement::Types::Attribute3;
|
||||
break;
|
||||
default:
|
||||
LOG(Error, "Vertex Shader '{}' (asset '{}') uses deprecated attribute index. Valid range is 0-3.", String(meta.Name), context->Options->TargetName);
|
||||
data.Type = VertexElement::Types::Attribute;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case VertexShaderMeta::InputType::BLENDINDICES:
|
||||
data.Type = VertexElement::Types::BlendIndices;
|
||||
break;
|
||||
case VertexShaderMeta::InputType::BLENDWEIGHT:
|
||||
data.Type = VertexElement::Types::BlendWeight;
|
||||
break;
|
||||
default:
|
||||
data.Type = VertexElement::Types::Unknown;
|
||||
break;
|
||||
}
|
||||
data.Slot = element.InputSlot;
|
||||
data.Offset = element.AlignedByteOffset != INPUT_LAYOUT_ELEMENT_ALIGN && element.AlignedByteOffset <= MAX_uint8 ? element.AlignedByteOffset : 0;
|
||||
data.PerInstance = element.InputSlotClass == INPUT_LAYOUT_ELEMENT_PER_INSTANCE_DATA;
|
||||
data.Format = element.Format;
|
||||
output->Write(data);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "Engine/Content/Assets/MaterialBase.h"
|
||||
#include "Engine/Content/AssetReference.h"
|
||||
#include "Engine/Core/Log.h"
|
||||
#include "Engine/Graphics/Shaders/GPUVertexLayout.h"
|
||||
#include "Engine/Renderer/DrawCall.h"
|
||||
|
||||
// Must match structure defined in Terrain.shader
|
||||
@@ -25,7 +26,6 @@ struct TerrainVertex
|
||||
class GeometryData
|
||||
{
|
||||
public:
|
||||
|
||||
GPUBuffer* VertexBuffer;
|
||||
GPUBuffer* IndexBuffer;
|
||||
uint32 IndicesCount;
|
||||
@@ -49,11 +49,11 @@ ChunkedArray<GeometryData, 1024> Pool;
|
||||
Dictionary<uint32, GeometryData*> Lookup;
|
||||
Array<byte> TempData;
|
||||
AssetReference<MaterialBase> DefaultTerrainMaterial;
|
||||
GPUVertexLayout* TerrainVertexLayout = nullptr;
|
||||
|
||||
class TerrainManagerService : public EngineService
|
||||
{
|
||||
public:
|
||||
|
||||
TerrainManagerService()
|
||||
: EngineService(TEXT("Terrain Manager"), 40)
|
||||
{
|
||||
@@ -132,7 +132,14 @@ bool TerrainManager::GetChunkGeometry(DrawCall& drawCall, int32 chunkSize, int32
|
||||
vertex++;
|
||||
}
|
||||
}
|
||||
auto desc = GPUBufferDescription::Vertex(sizeof(TerrainVertex), vertexCount2, TempData.Get());
|
||||
if (!TerrainVertexLayout)
|
||||
{
|
||||
TerrainVertexLayout = GPUVertexLayout::Get({
|
||||
{ VertexElement::Types::TexCoord0, 0, 0, 0, PixelFormat::R32G32_Float },
|
||||
{ VertexElement::Types::TexCoord1, 0, 0, 0, PixelFormat::R8G8B8A8_UNorm },
|
||||
});
|
||||
}
|
||||
auto desc = GPUBufferDescription::Vertex(TerrainVertexLayout, sizeof(TerrainVertex), vertexCount2, TempData.Get());
|
||||
if (vb->Init(desc))
|
||||
{
|
||||
Delete(vb);
|
||||
|
||||
@@ -2242,7 +2242,7 @@ void TerrainPatch::CacheDebugLines()
|
||||
typedef DebugDraw::Vertex Vertex;
|
||||
if (_debugLines->GetElementsCount() != count)
|
||||
{
|
||||
if (_debugLines->Init(GPUBufferDescription::Vertex(sizeof(Vertex), count)))
|
||||
if (_debugLines->Init(GPUBufferDescription::Vertex(Vertex::GetLayout(), sizeof(Vertex), count)))
|
||||
return;
|
||||
}
|
||||
Array<Vertex> debugLines;
|
||||
|
||||
@@ -27,9 +27,9 @@ TextRender::TextRender(const SpawnParams& params)
|
||||
: Actor(params)
|
||||
, _size(32)
|
||||
, _ib(0, sizeof(uint16))
|
||||
, _vb0(0, sizeof(VB0ElementType))
|
||||
, _vb1(0, sizeof(VB1ElementType))
|
||||
, _vb2(0, sizeof(VB2ElementType))
|
||||
, _vb0(0, sizeof(VB0ElementType), String::Empty, VB0ElementType::GetLayout())
|
||||
, _vb1(0, sizeof(VB1ElementType), String::Empty, VB1ElementType::GetLayout())
|
||||
, _vb2(0, sizeof(VB2ElementType), String::Empty, VB2ElementType::GetLayout())
|
||||
{
|
||||
_color = Color::White;
|
||||
_localBox = BoundingBox(Vector3::Zero);
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
// Meta macros used by shaders parser
|
||||
#define META_VS(isVisible, minFeatureLevel)
|
||||
#define META_VS_IN_ELEMENT(type, index, format, slot, offset, slotClass, stepRate, isVisible)
|
||||
#define META_VS_IN_ELEMENT(type, index, format, slot, offset, slotClass, stepRate, isVisible) // [Deprecated in v1.10]
|
||||
#define META_HS(isVisible, minFeatureLevel)
|
||||
#define META_HS_PATCH(inControlPoints)
|
||||
#define META_DS(isVisible, minFeatureLevel)
|
||||
|
||||
@@ -18,8 +18,6 @@ struct VS2PS
|
||||
Texture2D SceneDepthTexture : register(t0);
|
||||
|
||||
META_VS(true, FEATURE_LEVEL_ES2)
|
||||
META_VS_IN_ELEMENT(POSITION, 0, R32G32B32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(COLOR, 0, R8G8B8A8_UNORM, 0, ALIGN, PER_VERTEX, 0, true)
|
||||
VS2PS VS(float3 Position : POSITION, float4 Color : COLOR)
|
||||
{
|
||||
VS2PS output;
|
||||
|
||||
@@ -42,7 +42,6 @@ struct PixelInput
|
||||
// Vertex shader function for grid rendering
|
||||
META_VS(true, FEATURE_LEVEL_ES2)
|
||||
META_VS_IN_ELEMENT(POSITION, 0, R32G32B32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(TEXCOORD, 0, R16G16_FLOAT, 1, ALIGN, PER_VERTEX, 0, true)
|
||||
VertexOutput VS_Grid(ModelInput input)
|
||||
{
|
||||
VertexOutput output;
|
||||
|
||||
@@ -40,9 +40,6 @@ struct AtlasVertexOutput
|
||||
|
||||
// Vertex shader for Global Surface Atlas rendering (custom vertex buffer to render per-tile)
|
||||
META_VS(true, FEATURE_LEVEL_SM5)
|
||||
META_VS_IN_ELEMENT(POSITION, 0, R16G16_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(TEXCOORD, 0, R16G16_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(TEXCOORD, 1, R32_UINT, 0, ALIGN, PER_VERTEX, 0, true)
|
||||
AtlasVertexOutput VS_Atlas(AtlasVertexInput input)
|
||||
{
|
||||
AtlasVertexOutput output;
|
||||
|
||||
@@ -23,11 +23,6 @@ META_CB_END
|
||||
Texture2D Image : register(t0);
|
||||
|
||||
META_VS(true, FEATURE_LEVEL_ES2)
|
||||
META_VS_IN_ELEMENT(POSITION, 0, R32G32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(TEXCOORD, 0, R16G16_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(COLOR, 0, R32G32B32A32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(TEXCOORD, 1, R32G32B32A32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(TEXCOORD, 2, R32G32B32A32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
|
||||
VS2PS VS(Render2DVertex input)
|
||||
{
|
||||
VS2PS output;
|
||||
|
||||
@@ -16,30 +16,22 @@ META_CB_END
|
||||
|
||||
// Vertex Shader for screen space quad rendering
|
||||
META_VS(true, FEATURE_LEVEL_ES2)
|
||||
META_VS_IN_ELEMENT(POSITION, 0, R32G32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(TEXCOORD, 0, R32G32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
|
||||
Quad_VS2PS VS(float2 Position : POSITION0, float2 TexCoord : TEXCOORD0)
|
||||
{
|
||||
Quad_VS2PS output;
|
||||
|
||||
output.Position = float4(Position, 0, 1);
|
||||
output.TexCoord = TexCoord;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
// Vertex Shader function for postFx materials rendering
|
||||
META_VS(true, FEATURE_LEVEL_ES2)
|
||||
META_VS_IN_ELEMENT(POSITION, 0, R32G32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(TEXCOORD, 0, R32G32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
|
||||
MaterialVertexOutput VS_PostFx(float2 Position : POSITION0, float2 TexCoord : TEXCOORD0)
|
||||
{
|
||||
MaterialVertexOutput output;
|
||||
|
||||
output.Position = float4(Position, 0, 1);
|
||||
output.WorldPosition = output.Position.xyz;
|
||||
output.TexCoord = TexCoord;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
@@ -112,7 +112,6 @@ float3 GetVolumeUV(float3 worldPosition, float4x4 worldToClip)
|
||||
// Vertex shader that writes to a range of slices of a volume texture
|
||||
META_VS(true, FEATURE_LEVEL_SM5)
|
||||
META_FLAG(VertexToGeometryShader)
|
||||
META_VS_IN_ELEMENT(TEXCOORD, 0, R32G32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
|
||||
Quad_VS2GS VS_WriteToSlice(float2 TexCoord : TEXCOORD0, uint LayerIndex : SV_InstanceID)
|
||||
{
|
||||
Quad_VS2GS output;
|
||||
|
||||
Reference in New Issue
Block a user