#pragma region CPL License /* Nuclex Native Framework Copyright (C) 2002-2013 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #pragma endregion // CPL License // If the library is compiled as a DLL, this ensures symbols are exported #define NUCLEX_GRAPHICS_SOURCE 1 #include "Nuclex/Graphics/Rasterization/Shader.h" #include "Nuclex/Graphics/Rasterization/Limits.h" #include "Nuclex/Graphics/Introspection/ShaderReflector.h" #include #include #undef min #undef max namespace Nuclex { namespace Graphics { namespace Rasterization { // ------------------------------------------------------------------------------------------- // Shader::Shader(const std::uint8_t *const bytecode, std::size_t length) : bytecode(new std::uint8_t[length]), length(length), constantBuffers(new std::shared_ptr[ConstantBufferSlotCount]), textures(new std::shared_ptr[TextureSlotCount]) { std::copy_n(bytecode, this->length, this->bytecode); this->metadata = Introspection::ShaderReflector::Read(bytecode, length); } // ------------------------------------------------------------------------------------------- // Shader::Shader(const Shader &other) : bytecode(new std::uint8_t[other.length]), length(other.length), constantBuffers(new std::shared_ptr[ConstantBufferSlotCount]), textures(new std::shared_ptr[TextureSlotCount]) { for(std::size_t index = 0; index < ConstantBufferSlotCount; ++index) { this->constantBuffers[index] = other.constantBuffers[index]; } for(std::size_t index = 0; index < TextureSlotCount; ++index) { this->textures[index] = other.textures[index]; } std::copy_n(other.bytecode, this->length, this->bytecode); this->metadata.reset(new Introspection::ShaderMetadata(*other.metadata.get())); } // ------------------------------------------------------------------------------------------- // Shader::~Shader() { delete []this->bytecode; } // ------------------------------------------------------------------------------------------- // std::size_t Shader::CountConstantBufferSlots() const { return ConstantBufferSlotCount; } // ------------------------------------------------------------------------------------------- // const std::shared_ptr Shader::GetConstantBuffer( std::size_t index ) const { if(index >= ConstantBufferSlotCount) { throw std::out_of_range("Constant buffer index out of range"); } return this->constantBuffers[index]; } // ------------------------------------------------------------------------------------------- // void Shader::SetConstantBuffer( std::size_t index, const std::shared_ptr &constantBuffer ) { if(index >= ConstantBufferSlotCount) { throw std::out_of_range("Constant buffer index out of range"); } this->constantBuffers[index] = constantBuffer; OnConstantBufferChanged(index); } // ------------------------------------------------------------------------------------------- // std::size_t Shader::CountTextureSlots() const { return TextureSlotCount; } // ------------------------------------------------------------------------------------------- // const std::shared_ptr Shader::GetTexture(std::size_t index) const { if(index >= TextureSlotCount) { throw std::out_of_range("Texture slot index out of range"); } return this->textures[index]; } // ------------------------------------------------------------------------------------------- // void Shader::SetTexture(std::size_t index, const std::shared_ptr &texture) { if(index >= TextureSlotCount) { throw std::out_of_range("Texture slot index out of range"); } this->textures[index] = texture; OnTextureChanged(index); } // ------------------------------------------------------------------------------------------- // Shader::Observer *Shader::GetObserver(const void *owner) const { return this->observers.Get(owner); } // ------------------------------------------------------------------------------------------- // void Shader::AttachObserver(const void *owner, Observer *observer) { using namespace std; bool wasUnique = this->observers.AttachUnique(owner, observer); // Observer management should be accurate and error-free! assert(wasUnique && "Only one observer can be attached per owner"); wasUnique; // avoid unreferenced parameter warning } // ------------------------------------------------------------------------------------------- // void Shader::DetachObserver(const void *owner) { using namespace std; bool wasAttached = this->observers.Detach(owner); // Observer management should be accurate and error-free! assert(wasAttached && "Attempted to detach an observer that was not attached"); wasAttached; // avoid unreferenced parameter warning } // ------------------------------------------------------------------------------------------- // Shader &Shader::operator =(const Shader &) { throw std::runtime_error("Not implemented yet"); /* if(other.usedBytes > this->CapacityBytes) { throw std::runtime_error("Other Shader is too large for this Shader's capacity"); } std::copy_n(other.Contents, this->usedBytes, this->Contents); this->usedBytes = other.usedBytes; OnChanged(0, this->usedBytes); */ } // ------------------------------------------------------------------------------------------- // void Shader::OnDestroying() { std::vector copy = this->observers.Copy(); for(std::size_t index = 0; index < copy.size(); ++index) { copy[index]->Destroying(); } } // ------------------------------------------------------------------------------------------- // void Shader::OnConstantBufferChanged(std::size_t constantBufferIndex) { std::vector copy = this->observers.Copy(); for(std::size_t index = 0; index < copy.size(); ++index) { copy[index]->ConstantBufferChanged(constantBufferIndex); } } // ------------------------------------------------------------------------------------------- // void Shader::OnTextureChanged(std::size_t textureIndex) { std::vector copy = this->observers.Copy(); for(std::size_t index = 0; index < copy.size(); ++index) { copy[index]->TextureChanged(textureIndex); } } // ------------------------------------------------------------------------------------------- // }}} // namespace Nuclex::Graphics::Rasterization